{"id":2389,"date":"2017-10-29T15:23:09","date_gmt":"2017-10-29T14:23:09","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?p=2389"},"modified":"2017-10-29T15:23:09","modified_gmt":"2017-10-29T14:23:09","slug":"generating-custom-code-with-the-angular-cli-and-schematics","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/","title":{"rendered":"Generating Custom Code With The Angular CLI And Schematics"},"content":{"rendered":"<div class=\"article\">\n<hr>\n<p><b>Table of Contents<\/b><\/p>\n<p>This blog post is part of an article series.<\/p>\n<ul>\n<li><a href=\"https:\/\/www.angulararchitects.io\/post\/2017\/10\/29\/generating-custom-code-with-the-angular-cli-and-schematics.aspx\" rel=\"nofollow\">Part I: Generating Custom Code With The Angular CLI And Schematics<\/a><\/li>\n<li><a href=\"https:\/\/www.angulararchitects.io\/post\/2017\/12\/01\/generating-angular-code-with-schematics-part-ii-modifying-ngmodules.aspx\" rel=\"nofollow\">Part II: Automatically Updating Angular Modules With Schematics And The CLI<\/a><\/li>\n<li><a href=\"https:\/\/www.angulararchitects.io\/post\/2018\/01\/02\/angular-cli-and-schematics-part-iii-typescripts-compiler-api.aspx\" rel=\"nofollow\">Part III: Extending Existing Code With The TypeScript Compiler API<\/a><\/li>\n<li><a href=\"https:\/\/www.angulararchitects.io\/post\/2018\/03\/20\/custom-schematics-part-iv-frictionless-library-setup-with-the-angular-cli-and-schematics.aspx\" target=\"_blank\" rel=\"noopener\">Part IV:&nbsp;Frictionless Library Setup with the Angular CLI and Schematics<\/a><\/li>\n<li><a href=\"https:\/\/www.angulararchitects.io\/post\/2018\/04\/17\/seamlessly-updating-your-angular-libraries-with-ng-update.aspx\">Part V: Seamlessly Updating your Angular Libraries with ng update<\/a><\/li>\n<\/ul>\n<hr>\n<p><strong>Update, 2018-05-08<\/strong>: Updated for newest CLI version.<\/p>\n<p>Since some versions, the Angular CLI uses a library called <a href=\"https:\/\/www.npmjs.com\/package\/@angular-devkit\/schematics\">Schematics<\/a> to scaffold building blocks like components or services. One of the best things about this is that Schematics allows to create own code generators too. Using this extension mechanism, we can <a href=\"https:\/\/blog.angularindepth.com\/creating-your-own-application-template-for-angular-cli-95e22319cc24\">modify the way the CLI generates code<\/a>. But we can also provide custom collections with code generators and publish them as npm packages. A good example for this is <a href=\"https:\/\/nrwl.io\/nx\">Nrwl's Nx<\/a> which allows to generated boilerplate code for <a href=\"https:\/\/github.com\/ngrx\">Ngrx<\/a> or upgrading an existing application from AngularJS 1.x to Angular.<\/p>\n<p>These code generators are called Schematics and can not only create new files but also modify existing ones. For instance, the CLI uses the latter idea to register generated components with existing modules.<\/p>\n<p>In this post, I'm showing how to create a collection with a custom Schematic from scratch and how to use it with an Angular project. The <a href=\"https:\/\/github.com\/manfredsteyer\/schematics-sample\">sources<\/a> can be found <a href=\"https:\/\/github.com\/manfredsteyer\/schematics-sample\">here<\/a>.<\/p>\n<p>In addition to this, you'll find a nice <a href=\"https:\/\/www.youtube.com\/watch?v=ZKyz0lb0GjA\">video with Mike Brocchi from the CLI-Team explaining the basics and ideas behind Schematics here<\/a>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/y8LIiVg.png\" alt=\"Angular Labs\"><\/p>\n<blockquote><p>\nThe public API of Schematics is currently experimental and can change in future.\n<\/p><\/blockquote>\n<h2 id=\"goal\">Goal<\/h2>\n<p>To demonstrate how to write a simple Schematic from scratch, I will build a code generator for a Bootstrap based side menu. With an respective template like the free ones at <a href=\"https:\/\/www.creative-tim.com\/\">Creative Tim<\/a> the result could look like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i.imgur.com\/6Tqcekm.png\" alt=\"Solution\"><\/p>\n<p>Before creating a generator it is a good idea to have an existing solution that contains the code you want to generate in all variations.<\/p>\n<p>In our case, the component is quite simple:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">import<\/span> { Component, OnInit } from <span class=\"hljs-string\">'@angular\/core'<\/span>;\n\n@Component({\n    selector: <span class=\"hljs-string\">'menu'<\/span>,\n    templateUrl: <span class=\"hljs-string\">'menu.component.html'<\/span>\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> MenuComponent {\n}\n<\/div><\/code><\/pre>\n<p>In addition to that, the template for this component is just a bunch of html tags with the right Bootstrap based classes -- something I cannot learn by heart what's the reason a generator seems to be a good idea:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"sidebar-wrapper\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"logo\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"simple-text\"<\/span>&gt;<\/span>\n            AppTitle\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"nav\"<\/span>&gt;<\/span>\n\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">i<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"ti-home\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">i<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Home<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n\n        <span class=\"hljs-comment\">&lt;!-- add here some other items as shown before --&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/div><\/code><\/pre>\n<p>In addition to the code shown before, I want also have the possibility to create a more dynamic version of this side menu. This version uses an interface <code>MenuItem<\/code> to represent the items to display:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">interface<\/span> MenuItem {\n    title: <span class=\"hljs-built_in\">string<\/span>;\n    iconClass: <span class=\"hljs-built_in\">string<\/span>;\n}\n<\/div><\/code><\/pre>\n<p>A <code>MenuService<\/code> is providing instances of <code>MenuItem<\/code>:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">import<\/span> { MenuItem } from <span class=\"hljs-string\">'.\/menu-item'<\/span>;\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> MenuService {\n\n    <span class=\"hljs-keyword\">public<\/span> items: MenuItem[] = [\n        { title: <span class=\"hljs-string\">'Home'<\/span>, iconClass: <span class=\"hljs-string\">'ti-home'<\/span> },\n        { title: <span class=\"hljs-string\">'Other Menu Item'<\/span>, iconClass: <span class=\"hljs-string\">'ti-arrow-top-right'<\/span> },\n        { title: <span class=\"hljs-string\">'Further Menu Item'<\/span>, iconClass: <span class=\"hljs-string\">'ti-shopping-cart'<\/span>},\n        { title: <span class=\"hljs-string\">'Yet another one'<\/span>, iconClass: <span class=\"hljs-string\">'ti-close'<\/span>}\n    ];\n\n}\n<\/div><\/code><\/pre>\n<p>The component gets an instance of the service by the means of dependency injection:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">import<\/span> { Component, OnInit } from <span class=\"hljs-string\">'@angular\/core'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { menuItem } from <span class=\"hljs-string\">'.\/menu-item'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { menuService } from <span class=\"hljs-string\">'.\/menu.service'<\/span>;\n\n@Component({\n    selector: <span class=\"hljs-string\">'menu'<\/span>,\n    templateUrl: <span class=\"hljs-string\">'.\/menu.component.html'<\/span>,\n    providers:[MenuService]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> MenuComponent {\n\n    items: MenuItem[];\n\n    <span class=\"hljs-keyword\">constructor<\/span>(service: MenuService) {\n        <span class=\"hljs-keyword\">this<\/span>.items = service.items;\n    }\n}\n<\/div><\/code><\/pre>\n<p>After fetching the <code>MenuItems<\/code> from the service the component iterates over them using <code>*ngFor<\/code> and creates the needed markup:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"sidebar-wrapper\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"logo\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"simple-text\"<\/span>&gt;<\/span>\n            AppTitle\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"nav\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span> *<span class=\"hljs-attr\">ngFor<\/span>=<span class=\"hljs-string\">\"let item of items\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#\"<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">i<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"{{item.iconClass}}\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">i<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>{{item.title}}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/div><\/code><\/pre>\n<p>Even though this example is quite easy it provides enough stuff to demonstrate the basics of Schematics.<\/p>\n<h2 id=\"scaffolding-a-collection-for-schematics-with-schematics\">Scaffolding a Collection for Schematics ... with Schematics<\/h2>\n<p>To provide a project structure for an npm package with a Schematics Collection, we can leverage Schematics itself. The reason is that the product team provides a \"meta schematic\" for this. To get everything up and running we need to install the following npm package:<\/p>\n<pre><code>npm i -g @angular-devkit\/schematics-cli\n<\/code><\/pre>\n<p>In order to get our collection scaffolded we just need to type in the following command:<\/p>\n<pre><code>schematics schematic --name nav\n<\/code><\/pre>\n<p>After executing this command we get an npm package with a collection that holds three demo schematics:<\/p>\n<p><img decoding=\"async\" width=\"300\" src=\"https:\/\/i.imgur.com\/BDZ1UnF.png\" alt=\"npm package with collection\"><\/p>\n<p>The file <code>collection.json<\/code> contains metadata about the collection and points to the schematics in the three sub folders. Each schematic has meta data of its own describing the command line arguments it supports as well as generator code. Usually, they also contain template files with placeholders used for generating code. But more about this in the following sections.<\/p>\n<p>Before we can start, we need to <code>npm install<\/code> the dependencies the generated <code>package.json<\/code> points to. In addition to that, it is a good idea to rename its section <code>dependencies<\/code> to <code>devDependencies<\/code> because we don't want to install them when we load the npm package into a project:<\/p>\n<pre class=\"hljs\"><code><div>{\n  <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"nav\"<\/span>,\n  <span class=\"hljs-attr\">\"version\"<\/span>: <span class=\"hljs-string\">\"0.0.0\"<\/span>,\n  <span class=\"hljs-attr\">\"description\"<\/span>: <span class=\"hljs-string\">\"A schematics\"<\/span>,\n  <span class=\"hljs-attr\">\"scripts\"<\/span>: {\n    <span class=\"hljs-attr\">\"build\"<\/span>: <span class=\"hljs-string\">\"tsc -p tsconfig.json\"<\/span>,\n    <span class=\"hljs-attr\">\"test\"<\/span>: <span class=\"hljs-string\">\"npm run build &amp;&amp; jasmine **\/*_spec.js\"<\/span>\n  },\n  <span class=\"hljs-attr\">\"keywords\"<\/span>: [\n    <span class=\"hljs-string\">\"schematics\"<\/span>\n  ],\n  <span class=\"hljs-attr\">\"author\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n  <span class=\"hljs-attr\">\"license\"<\/span>: <span class=\"hljs-string\">\"MIT\"<\/span>,\n  <span class=\"hljs-attr\">\"schematics\"<\/span>: <span class=\"hljs-string\">\".\/src\/collection.json\"<\/span>,\n  <span class=\"hljs-attr\">\"devDependencies\"<\/span>: {\n    <span class=\"hljs-attr\">\"@angular-devkit\/core\"<\/span>: <span class=\"hljs-string\">\"^0.6.0\"<\/span>,\n    <span class=\"hljs-attr\">\"@angular-devkit\/schematics\"<\/span>: <span class=\"hljs-string\">\"^0.6.0\"<\/span>,\n    <span class=\"hljs-attr\">\"@types\/jasmine\"<\/span>: <span class=\"hljs-string\">\"^2.6.0\"<\/span>,\n    <span class=\"hljs-attr\">\"@types\/node\"<\/span>: <span class=\"hljs-string\">\"^8.0.31\"<\/span>,\n    <span class=\"hljs-attr\">\"jasmine\"<\/span>: <span class=\"hljs-string\">\"^2.8.0\"<\/span>,\n    <span class=\"hljs-attr\">\"typescript\"<\/span>: <span class=\"hljs-string\">\"^2.5.2\"<\/span>\n  }\n}\n<\/div><\/code><\/pre>\n<p>As you saw in the last listing, the <code>packages.json<\/code> contains a field <code>schematics<\/code> which is pointing to the file <code>collection.json<\/code> to inform about the metadata.<\/p>\n<h2 id=\"adding-an-custom-schematic\">Adding an custom Schematic<\/h2>\n<p>The three generated schematics contain comments that describe quite well how Schematics works. It is a good idea to have a look at them. For this tutorial, I've deleted them to concentrate on my own schematic. For this, I'm using the following structure:<\/p>\n<p><img decoding=\"async\" width=\"300\" src=\"https:\/\/i.imgur.com\/j91lJce.png\" alt=\"Structure for custom Schematics\"><\/p>\n<p>If you don't need the sample schematics you can also use the following command to create an empty scheamtics project:<\/p>\n<pre><code>schematics blank --name myProject\n<\/code><\/pre>\n<p>The new folder <code>menu<\/code> contains the custom schematic. It's command line arguments are described by the file <code>schema.json<\/code> using a JSON schema. The described data structure can also be found as an interface within the file <code>schema.ts<\/code>. Normally it would be a good idea to generate this interface out of the schema but for this easy case I've just handwritten it.<\/p>\n<p>The <code>index.ts<\/code> contains the so called factory for the schematic. This is a function that generates a rule (containing other rules) which describes how the code can be scaffolded. The templates used for this are located in the <code>files<\/code> folder. We will have a look at them later.<\/p>\n<p>First of all, let's update the <code>collection.json<\/code> to make it point to our menu schematic:<\/p>\n<pre class=\"hljs\"><code><div>{\n    <span class=\"hljs-attr\">\"schematics\"<\/span>: {\n      <span class=\"hljs-attr\">\"menu\"<\/span>: {\n        <span class=\"hljs-attr\">\"aliases\"<\/span>: [ <span class=\"hljs-string\">\"mnu\"<\/span> ],\n        <span class=\"hljs-attr\">\"factory\"<\/span>: <span class=\"hljs-string\">\".\/menu\"<\/span>,\n        <span class=\"hljs-attr\">\"description\"<\/span>: <span class=\"hljs-string\">\"Generates a menu component\"<\/span>,\n        <span class=\"hljs-attr\">\"schema\"<\/span>: <span class=\"hljs-string\">\".\/menu\/schema.json\"<\/span>\n      }\n    }\n}\n<\/div><\/code><\/pre>\n<p>Here we have an property <code>menu<\/code> for the menu schematic. This is also the name we reference when calling it. The array <code>aliases<\/code> contains other possible names to use and <code>factory<\/code> points to the file with the schematic's factory. Here, it points to <code>.\/menu<\/code> which is just a folder. That's why the factory is looked up in the file <code>.\/menu\/index.js<\/code>.<\/p>\n<p>In addition to that, the <code>collection.json<\/code> also points to the schema with the command line arguments. This file describes a property for each possible argument:<\/p>\n<pre class=\"hljs\"><code><div>{\n    <span class=\"hljs-attr\">\"$schema\"<\/span>: <span class=\"hljs-string\">\"http:\/\/json-schema.org\/schema\"<\/span>,\n    <span class=\"hljs-attr\">\"id\"<\/span>: <span class=\"hljs-string\">\"SchemanticsForMenu\"<\/span>,\n    <span class=\"hljs-attr\">\"title\"<\/span>: <span class=\"hljs-string\">\"Menu Schema\"<\/span>,\n    <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"object\"<\/span>,\n    <span class=\"hljs-attr\">\"properties\"<\/span>: {\n      <span class=\"hljs-attr\">\"name\"<\/span>: {\n        <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"string\"<\/span>,\n        <span class=\"hljs-attr\">\"$default\"<\/span>: {\n          <span class=\"hljs-attr\">\"$source\"<\/span>: <span class=\"hljs-string\">\"argv\"<\/span>,\n          <span class=\"hljs-attr\">\"index\"<\/span>: <span class=\"hljs-number\">0<\/span>\n        }\n      },\n      <span class=\"hljs-attr\">\"path\"<\/span>: {\n        <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"string\"<\/span>,\n        <span class=\"hljs-attr\">\"format\"<\/span>: <span class=\"hljs-string\">\"path\"<\/span>,\n        <span class=\"hljs-attr\">\"description\"<\/span>: <span class=\"hljs-string\">\"The path to create the component.\"<\/span>,\n        <span class=\"hljs-attr\">\"visible\"<\/span>: <span class=\"hljs-literal\">false<\/span>\n      },\n      <span class=\"hljs-attr\">\"project\"<\/span>: {\n        <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"string\"<\/span>,\n        <span class=\"hljs-attr\">\"description\"<\/span>: <span class=\"hljs-string\">\"The name of the project.\"<\/span>,\n        <span class=\"hljs-attr\">\"$default\"<\/span>: {\n          <span class=\"hljs-attr\">\"$source\"<\/span>: <span class=\"hljs-string\">\"projectName\"<\/span>\n        }\n      },      \n      <span class=\"hljs-attr\">\"module\"<\/span>:  {\n        <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"string\"<\/span>,\n        <span class=\"hljs-attr\">\"description\"<\/span>: <span class=\"hljs-string\">\"The declaring module.\"<\/span>,\n        <span class=\"hljs-attr\">\"alias\"<\/span>: <span class=\"hljs-string\">\"m\"<\/span>\n      },\n      <span class=\"hljs-attr\">\"menuService\"<\/span>: {\n        <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"boolean\"<\/span>,\n        <span class=\"hljs-attr\">\"default\"<\/span>: <span class=\"hljs-literal\">false<\/span>,\n        <span class=\"hljs-attr\">\"description\"<\/span>: <span class=\"hljs-string\">\"Flag to indicate whether an menu service should be generated.\"<\/span>,\n        <span class=\"hljs-attr\">\"alias\"<\/span>: <span class=\"hljs-string\">\"ms\"<\/span>\n      }\n\n    }\n  }\n\n<\/div><\/code><\/pre>\n<p>The argument <code>name<\/code> holds the name of the menu component. We find also the component's <code>path<\/code> and <code>module<\/code>. As an Angular application can contain several projects, the <code>project<\/code> property points to the right one.<\/p>\n<p>To prevent the developer from typing all those properties into the console, the schema.json points to defaults. For instance, <code>\"$source\": \"projectName\"<\/code> points to the Angular project in the current folder. To point to specific command line arguments, it is using <code>\"$source\": \"argv\"<\/code> with an respective <code>index<\/code>.<\/p>\n<p>I've also defined a property <code>menuService<\/code> to indicate, whether the above mentioned <code>service<\/code> class should be generated too.<\/p>\n<p>The interface for the schema within <code>schema.ts<\/code> is called <code>MenuOptions<\/code>:<\/p>\n<pre class=\"hljs\"><code><div>\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">interface<\/span> MenuOptions {\n    name: <span class=\"hljs-built_in\">string<\/span>;\n    project?: <span class=\"hljs-built_in\">string<\/span>;\n    path?: <span class=\"hljs-built_in\">string<\/span>;\n    <span class=\"hljs-keyword\">module<\/span>?: string;\n\n    menuService?: boolean;\n}\n<\/div><\/code><\/pre>\n<h2 id=\"schematic-factory\">Schematic Factory<\/h2>\n<p>To tell Schematics how to generated the requested code files, we need to provide a factory. This function describes the necessary steps with a rule which normally makes use of further rules:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">import<\/span> { MenuOptions } from <span class=\"hljs-string\">'.\/schema'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { Rule, [...] } from <span class=\"hljs-string\">'@angular-devkit\/schematics'<\/span>;\n[...]\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">options: MenuOptions<\/span>): <span class=\"hljs-title\">Rule<\/span> <\/span>{\n    [...]\n}\n<\/div><\/code><\/pre>\n<p>For this factory, I've defined two helper constructs at the top of the file:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">import<\/span> { strings } from <span class=\"hljs-string\">'@angular-devkit\/core'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { MenuOptions } from <span class=\"hljs-string\">'.\/schema'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { filter, Rule, [...] } from <span class=\"hljs-string\">'@angular-devkit\/schematics'<\/span>;<\/div><div><span class=\"hljs-keyword\">import<\/span> { parseName } from <span class=\"hljs-string\">'@schematics\/angular\/utility\/parse-name'<\/span>;\n<div style=\"color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); font-family: Consolas, &quot;Courier New&quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;\"><\/div><span class=\"hljs-keyword\">import<\/span> { getWorkspace } from <span class=\"hljs-string\">'@schematics\/angular\/utility\/config'<\/span>;\n<div style=\"color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); font-family: Consolas, &quot;Courier New&quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;\"><\/div>\n[...]\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">filterTemplates<\/span>(<span class=\"hljs-params\">options: MenuOptions<\/span>): <span class=\"hljs-title\">Rule<\/span> <\/span>{\n  <span class=\"hljs-keyword\">if<\/span> (!options.menuService) {\n    <span class=\"hljs-keyword\">return<\/span> filter(path =&gt; !path.match(<span class=\"hljs-regexp\">\/\\.service\\.ts$\/<\/span>) &amp;&amp; !path.match(<span class=\"hljs-regexp\">\/-item\\.ts$\/<\/span>) &amp;&amp; !path.match(<span class=\"hljs-regexp\">\/\\.bak$\/<\/span>));\n  }\n  <span class=\"hljs-keyword\">return<\/span> filter(path =&gt; !path.match(<span class=\"hljs-regexp\">\/\\.bak$\/<\/span>));\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">setupOptions<\/span>(<span class=\"hljs-params\">options: MenuOptions, host: Tree<\/span>): <span class=\"hljs-title\">void<\/span> <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> workspace = getWorkspace(host);\n  <span class=\"hljs-keyword\">if<\/span> (!options.project) {\n    options.project = <span class=\"hljs-built_in\">Object<\/span>.keys(workspace.projects)[<span class=\"hljs-number\">0<\/span>];\n  }\n  <span class=\"hljs-keyword\">const<\/span> project = workspace.projects[options.project];\n\n  <span class=\"hljs-keyword\">if<\/span> (options.path === <span class=\"hljs-literal\">undefined<\/span>) {\n    <span class=\"hljs-keyword\">const<\/span> projectDirName = project.projectType === <span class=\"hljs-string\">'application'<\/span> ? <span class=\"hljs-string\">'app'<\/span> : <span class=\"hljs-string\">'lib'<\/span>;\n    options.path = <span class=\"hljs-string\"><code>\/&lt;span class=&quot;hljs-subst&quot;&gt;${project.root}&lt;\/span&gt;\/src\/&lt;span class=&quot;hljs-subst&quot;&gt;${projectDirName}&lt;\/span&gt;<\/code><\/span>;\n  }\n\n  <span class=\"hljs-keyword\">const<\/span> parsedPath = parseName(options.path, options.name);\n  options.name = parsedPath.name;\n  options.path = parsedPath.path;\n\n}\n\n[...]\n<\/div><\/code><\/pre>\n<p>The imported object <code>strings<\/code> contains some functions we will need later within the templates, One of those functions is <code>dasherize<\/code> that transforms a name into its kebab case equivalent which can be used as a file name (e. g. <code>SideMenu<\/code> to <code>side-menu<\/code>) and <code>classify<\/code> transforms into Pascal case for class names (e. g. <code>side-menu<\/code> to <code>SideMenu<\/code>).<\/p>\n<p>The function <code>filterTemplates<\/code> creates a Rule that filters the templates within the folder <code>files<\/code>. For this, it delegates to the existing <code>filter<\/code> rule. Depending on whether the user requested a menu service, more or less template files are used. To make testing and debugging easier, I'm excluding <code>.bak<\/code> in each case.<\/p>\n<p>The function <code>setupOptions<\/code> makes sure we have all properties to generate our menu component. For this, it reads the CLI's configuration file with <code>getWorkspace<\/code> to get information about the configured projects. The the name of the project to use was not passed, it uses the first one. If no path was passed, it updates the path option with the defined project's root.<\/p>\n<p>Now let's have a look at the factory function:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">options: MenuOptions<\/span>): <span class=\"hljs-title\">Rule<\/span> <\/span>{\n\n    <span class=\"hljs-keyword\">return<\/span> (host: Tree, context: SchematicContext) =&gt; {\n\n      setupOptions(options, host);\n\n      <span class=\"hljs-keyword\">const<\/span> templateSource = apply(url(<span class=\"hljs-string\">'.\/files'<\/span>), [\n        filterTemplates(options),\n        template({\n          ...strings,\n          ...options\n        }),\n        move(options.path || <span class=\"hljs-string\">''<\/span>)\n      ]);\n\n      <span class=\"hljs-keyword\">const<\/span> rule = chain([\n        branchAndMerge(chain([\n          mergeWith(templateSource)\n        ]))\n      ]);\n\n      <span class=\"hljs-keyword\">return<\/span> rule(host, context);\n    }\n}\n<\/div><\/code><\/pre>\n<p>At the beginning, the factory deletes to <code>setupOptions<\/code>. Then, it uses <code>apply<\/code> to apply all templates within the <code>files<\/code> folder to the passed rules. After filtering the available templates they are executed with the rule returned by <code>template<\/code>. The passed properties are used within the templates. This creates a virtual folder structure with generated files that is moved to the current <code>path<\/code>.<\/p>\n<p>The resulting <code>templateSource<\/code> is a <code>Source<\/code> instance. It's responsibility is creating a <code>Tree<\/code> object that represents a file tree which can be either virtual or physical. Schematics uses virtual file trees as a staging area. Only when everything worked, it is merged with the physical file tree on your disk. You can also think about this as committing a transaction.<\/p>\n<p>At the end, the factory returns a rule created with the <code>chain<\/code> function (which is a rule too). It creates a new rule by chaining the passed ones. In this example we are just using the rule <code>mergeWith<\/code> but the enclosing <code>chain<\/code> makes it extendable.<\/p>\n<p>As the name implies, <code>mergeWith<\/code> merges the <code>Tree<\/code> represented by <code>templateSource<\/code> with the tree which represents the current Angular project.<\/p>\n<h2 id=\"templates\">Templates<\/h2>\n<p>Now it's time to look at our templates within the <code>files<\/code> folder:<\/p>\n<p><img decoding=\"async\" width=\"300\" src=\"https:\/\/i.imgur.com\/7F0pmpB.png\" alt=\"Folder with Templates\"><\/p>\n<p>The nice thing about this is that the file names are templates too. For instance <code>__x__<\/code> would be replaced with the contents of the variable <code>x<\/code> which is passed to the <code>template<\/code> rule. You can even call functions to transform these variables. In our case, we are using <code>__name@dasherize__<\/code> which passes the variable name to the function <code>dasherize<\/code> which in turn is passed to <code>template<\/code> too.<\/p>\n<p>The easiest one is the template for the item class which represents a menu item:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">interface<\/span> &lt;%= classify(name) %&gt;Item {\n    title: <span class=\"hljs-built_in\">string<\/span>;\n    iconClass: <span class=\"hljs-built_in\">string<\/span>;\n}\n<\/div><\/code><\/pre>\n<p>Like in other known template languages (e. g. PHP), we can execute code for the generation within the delimiters <code>&lt;%<\/code> and <code>%&gt;<\/code>. Here, we are using the short form <code>&lt;%=value%&gt;<\/code> to write a value to the generated file. This value is just the name the caller passed transformed with <code>classify<\/code> to be used as a class name.<\/p>\n<p>The template for the menu service is build in a similar way:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">import<\/span> { &lt;%= classify(name) %&gt;Item } from <span class=\"hljs-string\">'.\/&lt;%=dasherize(name)%&gt;-item'<\/span>;\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> &lt;%= classify(name) %&gt;Service {\n\n    <span class=\"hljs-keyword\">public<\/span> items: &lt;%= classify(name) %&gt;Item[] = [\n        { title: <span class=\"hljs-string\">'Home'<\/span>, iconClass: <span class=\"hljs-string\">'ti-home'<\/span> },\n        { title: <span class=\"hljs-string\">'Other Menu Item'<\/span>, iconClass: <span class=\"hljs-string\">'ti-arrow-top-right'<\/span> },\n        { title: <span class=\"hljs-string\">'Further Menu Item'<\/span>, iconClass: <span class=\"hljs-string\">'ti-shopping-cart'<\/span>},\n        { title: <span class=\"hljs-string\">'Yet another one'<\/span>, iconClass: <span class=\"hljs-string\">'ti-close'<\/span>}\n    ];\n}\n<\/div><\/code><\/pre>\n<p>In addition to that, the component template contains some <code>if<\/code> statements that check whether a menu service should be used:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">import<\/span> { Component, OnInit } from <span class=\"hljs-string\">'@angular\/core'<\/span>;\n&lt;% <span class=\"hljs-keyword\">if<\/span> (menuService) { %&gt;\n<span class=\"hljs-keyword\">import<\/span> { &lt;%= classify(name) %&gt;Item } from <span class=\"hljs-string\">'.\/&lt;%=dasherize(name)%&gt;-item'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { &lt;%= classify(name) %&gt;Service } from <span class=\"hljs-string\">'.\/&lt;%=dasherize(name)%&gt;.service'<\/span>;\n&lt;% } %&gt;\n\n@Component({\n    selector: <span class=\"hljs-string\">'&lt;%=dasherize(name)%&gt;'<\/span>,\n    templateUrl: <span class=\"hljs-string\">'&lt;%=dasherize(name)%&gt;.component.html'<\/span>,\n    &lt;% <span class=\"hljs-keyword\">if<\/span> (menuService) { %&gt;\n        providers: [&lt;%= classify(name) %&gt;Service]\n    &lt;% } %&gt;\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> &lt;%= classify(name) %&gt;Component {\n\n&lt;% <span class=\"hljs-keyword\">if<\/span> (menuService) { %&gt;\n    items: &lt;%= classify(name) %&gt;Item[];\n\n    <span class=\"hljs-keyword\">constructor<\/span>(service: &lt;%= classify(name) %&gt;Service) {\n        <span class=\"hljs-keyword\">this<\/span>.items = service.items;\n    }\n&lt;% } %&gt;\n\n}\n<\/div><\/code><\/pre>\n<p>The same is the case for the component's template. When the caller requested a menu service, it's using it; otherwise it just gets hardcoded sample items:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"sidebar-wrapper\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"logo\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"simple-text\"<\/span>&gt;<\/span>\n            AppTitle\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"nav\"<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">%<\/span> <span class=\"hljs-attr\">if<\/span> (<span class=\"hljs-attr\">menuService<\/span>) { %&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span> *<span class=\"hljs-attr\">ngFor<\/span>=<span class=\"hljs-string\">\"let item of items\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">i<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"{{item.iconClass}}\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">i<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>{{item.title}}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">%<\/span> } <span class=\"hljs-attr\">else<\/span> { %&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">i<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"ti-home\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">i<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Home<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">i<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"ti-arrow-top-right\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">i<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Other Menu Item<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">i<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"ti-shopping-cart\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">i<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Further Menu Item<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">i<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"ti-close\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">i<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Yet another one<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">%<\/span> } %&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/div><\/code><\/pre>\n<h2 id=\"building-and-testing-with-a-sample-application\">Building and Testing with a Sample Application<\/h2>\n<p>To build the npm package, we just need to call <code>npm run build<\/code> which is just triggering the TypeScript compiler.<\/p>\n<p>For testing it, we need a sample application that can be created with the CLI. Please make sure to use Angular CLI version 1.5 RC.4 or higher.<\/p>\n<p>For me, the easiest way to test the collection was to copy the whole package into the sample application's <code>node_module<\/code> folder so that everything ended up within <code>node_modules\/nav<\/code>. Please make sure to exclude the collection's <code>node_modules<\/code> folder, so that there is no folder <code>node_modules\/nav\/node_modules<\/code>.<\/p>\n<p>Instead of this, pointing to a relative folder with the collection should work too. In my experiments, I did with a release candidate, this wasn't the case (at least not in any case).<\/p>\n<p>After this, we can use the CLI to scaffold our side menu:<\/p>\n<pre><code>ng g nav:menu side-menu --menuService \n<\/code><\/pre>\n<p>Here, <code>menu<\/code> is the name of the schematic, <code>side-menu<\/code> the file name we are passing and <code>nav<\/code> the name of the npm package.<\/p>\n<p>After this, we need to register the generated component with the <code>AppModule<\/code>:<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-keyword\">import<\/span> { SideMenuComponent } from <span class=\"hljs-string\">'.\/side-menu\/side-menu.component'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { BrowserModule } from <span class=\"hljs-string\">'@angular\/platform-browser'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { NgModule } from <span class=\"hljs-string\">'@angular\/core'<\/span>;\n\n<span class=\"hljs-keyword\">import<\/span> { AppComponent } from <span class=\"hljs-string\">'.\/app.component'<\/span>;\n\n@NgModule({\n  declarations: [\n    AppComponent,\n    SideMenuComponent\n  ],\n  imports: [\n    BrowserModule\n  ],\n  providers: [],\n  bootstrap: [AppComponent]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> AppModule { }\n<\/div><\/code><\/pre>\n<p>In an other post, I will show how to even automate this task with Schematics.<\/p>\n<p>After this, we can call the component in our <code>AppModule<\/code>. The following sample also contains some boiler blade for the Bootstrap Theme used in the initial screen shot.<\/p>\n<pre class=\"hljs\"><code><div><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"wrapper\"<\/span>&gt;<\/span>\n\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"sidebar\"<\/span> <span class=\"hljs-attr\">data-background-color<\/span>=<span class=\"hljs-string\">\"white\"<\/span> <span class=\"hljs-attr\">data-active-color<\/span>=<span class=\"hljs-string\">\"danger\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">side-menu<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">side-menu<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"main-panel\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"content\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"card\"<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"header\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"title\"<\/span>&gt;<\/span>Hello World<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"content\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">\"padding:7px\"<\/span>&gt;<\/span>\n             Lorem ipsum ...\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/div><\/code><\/pre>\n<p>To get Bootstrap and the Bootstrap Theme, you can download the free version of the <a href=\"https:\/\/www.creative-tim.com\/\">paper theme<\/a> and copy it to your <code>assets<\/code> folder. Also reference the necessary files within the file <code>.angular-cli.json<\/code> to make sure they are copied to the output folder:<\/p>\n<pre><code>[...]\n\"styles\": [\n  \"styles.css\",\n  \"assets\/css\/bootstrap.min.css\",\n  \"assets\/css\/paper-dashboard.css\",\n  \"assets\/css\/demo.css\",\n  \"assets\/css\/themify-icons.css\"\n],\n[...]\n<\/code><\/pre>\n<p>After this, we can finally run our application: <code>ng serve<\/code>.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Generating Custom Code With The Angular CLI And Schematics<\/p>\n","protected":false},"author":9,"featured_media":2997,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2389","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-unkategorisiert"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Generating Custom Code With The Angular CLI And Schematics - ANGULARarchitects<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Generating Custom Code With The Angular CLI And Schematics - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"Generating Custom Code With The Angular CLI And Schematics\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2017-10-29T14:23:09+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1280\" \/>\n\t<meta property=\"og:image:height\" content=\"853\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Manfred Steyer, GDE\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@daniel\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer, GDE\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/\"},\"author\":{\"name\":\"Manfred Steyer, GDE\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\"},\"headline\":\"Generating Custom Code With The Angular CLI And Schematics\",\"datePublished\":\"2017-10-29T14:23:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/\"},\"wordCount\":1908,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"articleSection\":[\"Unkategorisiert\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/\",\"name\":\"Generating Custom Code With The Angular CLI And Schematics - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"datePublished\":\"2017-10-29T14:23:09+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg\",\"width\":1280,\"height\":853},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Generating Custom Code With The Angular CLI And Schematics\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"name\":\"ANGULARarchitects\",\"description\":\"AngularArchitects.io\",\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\",\"name\":\"ANGULARarchitects\",\"alternateName\":\"SOFTWAREarchitects\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"width\":644,\"height\":216,\"caption\":\"ANGULARarchitects\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/github.com\/angular-architects\",\"https:\/\/www.linkedin.com\/company\/angular-architects\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\",\"name\":\"Manfred Steyer, GDE\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer, GDE\"},\"sameAs\":[\"https:\/\/x.com\/daniel\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Generating Custom Code With The Angular CLI And Schematics - ANGULARarchitects","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/","og_locale":"en_US","og_type":"article","og_title":"Generating Custom Code With The Angular CLI And Schematics - ANGULARarchitects","og_description":"Generating Custom Code With The Angular CLI And Schematics","og_url":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/","og_site_name":"ANGULARarchitects","article_published_time":"2017-10-29T14:23:09+00:00","og_image":[{"width":1280,"height":853,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","type":"image\/jpeg"}],"author":"Manfred Steyer, GDE","twitter_card":"summary_large_image","twitter_creator":"@daniel","twitter_misc":{"Written by":"Manfred Steyer, GDE","Est. reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/"},"author":{"name":"Manfred Steyer, GDE","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951"},"headline":"Generating Custom Code With The Angular CLI And Schematics","datePublished":"2017-10-29T14:23:09+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/"},"wordCount":1908,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","articleSection":["Unkategorisiert"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/","url":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/","name":"Generating Custom Code With The Angular CLI And Schematics - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","datePublished":"2017-10-29T14:23:09+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/04\/blog-2355684-1280.jpg","width":1280,"height":853},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/generating-custom-code-with-the-angular-cli-and-schematics\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Generating Custom Code With The Angular CLI And Schematics"}]},{"@type":"WebSite","@id":"https:\/\/www.angulararchitects.io\/en\/#website","url":"https:\/\/www.angulararchitects.io\/en\/","name":"ANGULARarchitects","description":"AngularArchitects.io","publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.angulararchitects.io\/en\/#organization","name":"ANGULARarchitects","alternateName":"SOFTWAREarchitects","url":"https:\/\/www.angulararchitects.io\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","width":644,"height":216,"caption":"ANGULARarchitects"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/github.com\/angular-architects","https:\/\/www.linkedin.com\/company\/angular-architects\/"]},{"@type":"Person","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951","name":"Manfred Steyer, GDE","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","caption":"Manfred Steyer, GDE"},"sameAs":["https:\/\/x.com\/daniel"]}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/2389","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=2389"}],"version-history":[{"count":0,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/2389\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/2997"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=2389"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=2389"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=2389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}