In this tutorial you will learn how to define custom UI elements once and embed it into new projects by using a simple cli command.
In order to accomplish this automatic code generation we can use Angular Schematics.
As it is described on this page:
https://angular.dev/tools/cli/schematics-for-libraries#add-template-files
Get the source code for the example this article is based on from: https://github.com/Elipkm/ng-schematics
In this example the menu component below should be generated with a command.
The schematics project contains
- a
collection.json
(there are the templates defined and linked to a schematic name) - the different templates with:
->index.ts
(there happens the generation)
->schema.json
(there we can define the input parameters)
When a template is ready, we can build it with npm run build
. After that we can call npm link
to make it available for usage. You can call the template with the following command.
schematics my-angular-schematics:mytemplate --name=CuriousLayout
First Try
I tried to keep the first version to a simple minimum. First I defined my example component, the menu, and put it in a folder “files”. There I just changed the name, so when generating you can pass a name for the menu template component.
To replace the file name with the input parameter (‘name’) I defined the files the following way:
Filenames:
__name@dasherize__.component.html
__name@dasherize__.component.ts
__name@dasherize__.component.css
- Filecontent needs to specify the parameter with the following syntax:
<%= classify(name) %>
The Classify method is for the classname => “UpperCaseClass”.
The dasherize is for transforming astring into => “upper-case-class”.
The transformation of the parameter and the injection is defined at index.ts. with the templateSource definition and applied is the config by returning the Tree and calling mergeWith method.
Second Try
In this iteration I thought about the ability to provide a mechanism to customize a template and generate under certain conditions. A quick example to demonstrate this is a flag for displaying the menu whether as an ordered list or an unordered list.
One way to achieve this is to inject the schematic parameter into the .ts class as variable and then using angulars @if method in the .html template.
@if(preference === 'ul' || preference === 'unordered') {...}
This works fine but the result would look like this in the Component class:
preference: string = 'ul';
Third Try
The third template keeps the same functionality as the second but validates the conditions on the other side. If you like to keep the generated code and component clean from any conditional logic then you can process the input flag right at the index.ts and only generate a finished component.
Place the customizable ui elements in a separate file. I have now a preference folder containing a ordered-list.html and a unordered-list.html. The input flag is validated on the index.ts level before generating any code. Based on the flag a preference ui file is read into the program and is passed as template option that we can resolve in our html file with <%= myHtml =>