{"id":3105,"date":"2019-08-13T12:22:40","date_gmt":"2019-08-13T10:22:40","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?p=3105"},"modified":"2019-08-13T12:22:40","modified_gmt":"2019-08-13T10:22:40","slug":"architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/","title":{"rendered":"Architecture with Angular Ivy &#8211; Part 2: Higher order and dynamic Components"},"content":{"rendered":"<p>This article is part of an series:<\/p>\n<ul>\n<li class=\"code-line\" data-line=\"5\"><a title=\"https:\/\/www.angulararchitects.io\/aktuelles\/architecture-with-ivy-a-possible-future-without-angular-modules\/\" href=\"https:\/\/www.angulararchitects.io\/aktuelles\/architecture-with-ivy-a-possible-future-without-angular-modules\/\">Part 1: A possible future without Angular Modules<\/a><\/li>\n<li class=\"code-line\" data-line=\"6\">Part 2: Higher order and dynamic Components (this one)<\/li>\n<\/ul>\n<hr \/>\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"code-line\" data-line=\"9\"><strong>TLDR;<\/strong>\u00a0With Ivy's private APIs, we can dynamically create components. The example here demonstrates this by creating a routed component on the fly:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">const routes: Routes = [\n  {\n    path: 'comic\/:comicId',\n    component: withRoute(ComicComponent)\n  }\n];<\/pre>\n<p class=\"code-line\" data-line=\"21\">As an software architect, I'm constantly in search for ways to improve my applications's structures. The goal is nearly always to provide robust and more sustainable solutions. This is also a big topic in my\u00a0<a title=\"https:\/\/www.angulararchitects.io\/schulungen\/advanced-angular-enterprise-anwendungen-und-architektur\/\" href=\"https:\/\/www.angulararchitects.io\/schulungen\/advanced-angular-enterprise-anwendungen-und-architektur\/\">advanced Enterprise Angular workshop<\/a>.<\/p>\n<p class=\"code-line\" data-line=\"23\">Ivy provides some awesome features helping to reach these goals. In this article series, I show them in the context of several examples. I look behind the curtain of Angular's new view engine which helps us to understand better what's going on and what the future of Angular might look like.<\/p>\n<p class=\"code-line\" data-line=\"25\">This article shows how to use Ivy to generate components on the fly and how to create a higher order components. You can find the\u00a0<a title=\"https:\/\/github.com\/manfredsteyer\/ivy-dynamic-components-hoc\" href=\"https:\/\/github.com\/manfredsteyer\/ivy-dynamic-components-hoc\">source code<\/a>\u00a0of the example used here in my\u00a0<a title=\"https:\/\/github.com\/manfredsteyer\/ivy-dynamic-components-hoc\" href=\"https:\/\/github.com\/manfredsteyer\/ivy-dynamic-components-hoc\">GitHub account<\/a>.<\/p>\n<p data-line=\"25\"><strong>Big thanks<\/strong>, to Angular's\u00a0<a title=\"https:\/\/github.com\/alxhub\" href=\"https:\/\/github.com\/alxhub\">Alex Rickabaugh<\/a>\u00a0for reviewing this article and for giving me some hints about Ivy.<\/p>\n<p class=\"code-line\" data-line=\"29\"><strong>DISCLAIMER<\/strong>: The examples here are an\u00a0<strong>experiment<\/strong>showing how Ivy works under the covers by leveraging its\u00a0<strong>private APIs<\/strong>. Hence, it's not production ready and it\u00a0<strong>does not<\/strong>\u00a0reflect the Angular teams's official vision. Nethertheless, it's useful to learn how Ivy works and what features we might get via the official public APIs after Ivy landed.<\/p>\n<p class=\"code-line\" data-line=\"31\">Currently, the Angular team's goal is to make sure, there are no breaking changes after migrating to Ivy. After this, they will introduce new features based on Ivy step by step.<\/p>\n<h2 id=\"example\" class=\"code-line\" data-line=\"33\">Example<\/h2>\n<p class=\"code-line\" data-line=\"35\">The example I use here is a simple comic browser:<\/p>\n<p data-line=\"35\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3100\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/hoc-example.png\" alt=\"\" width=\"627\" height=\"908\" srcset=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/hoc-example.png 627w, https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/hoc-example-600x869.png 600w, https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/hoc-example-207x300.png 207w\" sizes=\"auto, (max-width: 627px) 100vw, 627px\" \/><\/p>\n<p data-line=\"35\">After selecting a comic from the list, the router puts the respective\u00a0<code>comicId<\/code>\u00a0into the URL and activates a\u00a0<code>RoutedComicComponent<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@Component({\n  selector: 'app-routed-comic',\n  templateUrl: '.\/routed-comic.component.html'\n})\nexport class RoutedComicComponent implements OnInit {\n\n  constructor(private route: ActivatedRoute) { }\n\n  params: any = {};\n\n  ngOnInit() {\n    this.route.params.subscribe(params =&gt; {\n      this.params = params;\n    });\n  }\n\n}<\/pre>\n<p>This component reads the parameters from the URL. The template binds them to the\u00a0<code>ComicComponent<\/code>\u00a0which displays the comic in question:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">&lt;app-comic [comicId]=\"params.comicId\"&gt;&lt;\/app-comic&gt;<\/pre>\n<p>To put it in a nutshell, we have a routed component which just delegates the routing parameters to an inner one, e. g. the\u00a0<code>app-comic<\/code>:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3101\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/hoc-picture.png\" alt=\"\" width=\"538\" height=\"414\" srcset=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/hoc-picture.png 538w, https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/hoc-picture-300x231.png 300w\" sizes=\"auto, (max-width: 538px) 100vw, 538px\" \/><\/p>\n<h2 id=\"goal\" class=\"code-line\" data-line=\"71\">Goal<\/h2>\n<p class=\"code-line\" data-line=\"73\">In our example, the\u00a0<code>RoutedComicComponent<\/code>\u00a0can be considered glue code. It's just here to read and delegate the parameters.<\/p>\n<p class=\"code-line\" data-line=\"75\">Of course, we could put this logic into the\u00a0<code>ComicComponent<\/code>\u00a0but then, this component would have to know the router including the current very specific routing configuration. In turn, it would become less reusable.<\/p>\n<p class=\"code-line\" data-line=\"77\">On the other side, the\u00a0<code>RoutedComicComponent<\/code>\u00a0would look very similar for other components. Only its encapsulated component needed to be exchanged. Hence, we can create this component on the fly for different encapsulated components.<\/p>\n<p class=\"code-line\" data-line=\"79\">As the next sections show, this task is quite easy with Ivy.<\/p>\n<h2 id=\"inspecting-the-result-of-the-ivy-compiler\" class=\"code-line\" data-line=\"81\">Inspecting the result of the Ivy compiler<\/h2>\n<p class=\"code-line\" data-line=\"83\">Before we go on, let's find out how Ivy transforms our\u00a0<code>RoutedComicComponent<\/code>\u00a0during the compilation. To make the compiled code more readable, we should switch to\u00a0<code>ES2015<\/code>\u00a0if this is not already the case. For this, make sure the\u00a0<code>target<\/code>\u00a0property in your\u00a0<code>tsconfig.json<\/code>points to\u00a0<code>ES2015<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">{\n  [...]\n  \"compilerOptions\": {\n    [...]\n    \"target\": \"es2015\",\n    [...]\n  },\n  [...]\n}<\/pre>\n<p>Also, make sure you are using Ivy. In this case, we need the following\u00a0<code>angularCompilerOptions<\/code>\u00a0node in our\u00a0<code>tsconfig.app.json<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">{\n  \"extends\": \".\/tsconfig.json\",\n  \"compilerOptions\": {\n    [...]\n  },\n  \"include\": [\n    [...]\n  ],\n  \"exclude\": [\n    [...]\n  ],\n  \"angularCompilerOptions\": {\n    \"enableIvy\": true\n  }\n}<\/pre>\n<p>After running\u00a0<code>ng build --aot<\/code>\u00a0we should find the downleveled version of our\u00a0<code>RoutedComicComponent<\/code>within the\u00a0<code>main<\/code>\u00a0bundle in the\u00a0<code>dist<\/code>\u00a0folder.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">class RoutedComicComponent {\n    constructor(route) {\n        this.route = route;\n        this.params = {};\n    }\n    ngOnInit() {\n        this.route.params.subscribe(params =&gt; {\n            this.params = params;\n        });\n    }\n}<\/pre>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">const _c0 = [3, \"comicId\"];\n\nRoutedComicComponent.ngComponentDef = \u0275\u0275defineComponent({\n    type: RoutedComicComponent, \n    selectors: [[\"app-routed-comic\"]], \n    factory: function RoutedComicComponent_Factory(t) { \n        return new (t || RoutedComicComponent)(\u0275\u0275directiveInject(ActivatedRoute)); \n    }, \n    consts: 1, \n    vars: 1, \n    template: function RoutedComicComponent_Template(rf, ctx) {\n        if (rf &amp; 1) {\n            \u0275\u0275element(0, \"app-comic\", _c0);\n        } if (rf &amp; 2) {\n            \u0275\u0275property(\"comicId\", ctx.params.comicId);\n        }\n    }, \n    directives: [ComicComponent], \n    styles: [\"...\"]\n});<\/pre>\n<p class=\"code-line\" data-line=\"156\">I've formatted this listing a bit and removed the webpack-based imports to make it more readable. As you can see, Ivy adds a static\u00a0<code>ngComponentDef<\/code>\u00a0property during compilation. It contains all the details, Angular needs to execute the component at runtime. Most of them are self explaining:<\/p>\n<ul>\n<li class=\"code-line\" data-line=\"158\">\n<p class=\"code-line\" data-line=\"158\"><code>type<\/code>: The component's type<\/p>\n<\/li>\n<li class=\"code-line\" data-line=\"159\">\n<p class=\"code-line\" data-line=\"159\"><code>selectors<\/code>: Each defined selector is an array within this array here.<\/p>\n<\/li>\n<li class=\"code-line\" data-line=\"160\">\n<p class=\"code-line\" data-line=\"160\"><code>factory<\/code>: Function creating the component. Please note that it also takes care of injecting the necessary dependencies.<\/p>\n<p class=\"code-line\" data-line=\"162\">The passed parameter\u00a0<code>t<\/code>\u00a0is only used for sub-classing. If a component\u00a0<code>MyComp<\/code>\u00a0inherits\u00a0<code>BaseComp<\/code>,\u00a0<code>MyComp<\/code>'s factory has to delegate to\u00a0<code>BaseComp<\/code>'s one. However, as you want to instantiate\u00a0<code>MyComp<\/code>\u00a0in this case,\u00a0<code>MyComp<\/code>\u00a0is passed as the parameter\u00a0<code>t<\/code>. This way,\u00a0<code>MyComp<\/code>\u00a0can also inherit the injections set up for\u00a0<code>BaseComp<\/code>.<\/p>\n<\/li>\n<li class=\"code-line\" data-line=\"164\">\n<p class=\"code-line\" data-line=\"164\"><code>const<\/code>: The count of nodes, local refs, and pipes in the template. This is used to initial an internal array with a proper length.<\/p>\n<\/li>\n<li class=\"code-line\" data-line=\"165\">\n<p class=\"code-line\" data-line=\"165\"><code>vars<\/code>: The same for the number of bindings.<\/p>\n<\/li>\n<li class=\"code-line\" data-line=\"166\">\n<p class=\"code-line\" data-line=\"166\"><code>template<\/code>: The compiled version of our HTML template.<\/p>\n<\/li>\n<li class=\"code-line\" data-line=\"167\">\n<p class=\"code-line\" data-line=\"167\"><code>directives<\/code>: Other directives and components our component can call. Ivy populates this array with entries from\u00a0<code>NgModule<\/code>s to be backwards competable. However,\u00a0<a title=\"https:\/\/www.angulararchitects.io\/aktuelles\/architecture-with-ivy-a-possible-future-without-angular-modules\/\" href=\"https:\/\/www.angulararchitects.io\/aktuelles\/architecture-with-ivy-a-possible-future-without-angular-modules\/\">as shown in my former post<\/a>, Ivy doesn't need\u00a0<code>NgModules<\/code>\u00a0anymore.<\/p>\n<\/li>\n<li class=\"code-line\" data-line=\"168\">\n<p class=\"code-line\" data-line=\"168\"><code>styles<\/code>: CSS rules<\/p>\n<\/li>\n<\/ul>\n<p class=\"code-line\" data-line=\"170\">Also note, that the used functions are prefixed with\u00a0<code>\u0275\u0275<\/code>which shows that we are talking about Ivy's internal and hence not public API. Hence, details can change over time.<\/p>\n<p class=\"code-line\" data-line=\"172\">Now, let's have a closer look at the template function. It's really nothing more than a JavaScript representation of our template. Instead of exchanging placeholders within HTML (or SVG, etc.), Angular uses this function in order to improve the data binding and rendering performance.<\/p>\n<p class=\"code-line\" data-line=\"174\">The passed parameter,\u00a0<code>rf<\/code>\u00a0(<code>RenderFlags<\/code>), denotes the rendering phase. Angular sets the first bit when it creates the component and the second bit when it updates its bindings. Hence, in the former case, the function creates the template's elements while in the latter one, it updates their bindings.<\/p>\n<p class=\"code-line\" data-line=\"176\">The second parameter,\u00a0<code>ctx<\/code>\u00a0(<code>Context<\/code>), points to the component instance.<\/p>\n<p class=\"code-line\" data-line=\"178\">For creating an element,\u00a0<code>\u0275\u0275element<\/code>\u00a0takes an unique id and the element's name. This ids which are ascending and start at 0 can be used later to reference this element. In our case, this name points to the component with the selector\u00a0<code>app-comic<\/code>. The last parameter,\u00a0<code>_c0<\/code>, informs \u0275\u0275element about attributes, properties, etc. The\u00a0<code>3<\/code>\u00a0in this array indicates that the next entry is a property we bind to and the following\u00a0<code>comicId<\/code>\u00a0is its name.<\/p>\n<p class=\"code-line\" data-line=\"180\">For updating this binding,\u00a0<code>\u0275\u0275property<\/code>\u00a0takes the property name and its new value. Perhaps you are wondering, how\u00a0<code>\u0275\u0275property<\/code>\u00a0knows which element we are referring to. In our case, it's easy as there is only one element.<\/p>\n<p class=\"code-line\" data-line=\"182\">By default,\u00a0<code>\u0275\u0275property<\/code>\u00a0uses the element with the internal id 0. To switch over to another one, Ivy calls\u00a0<code>\u0275\u0275select<\/code>\u00a0with the respective element id. For instance, to work on the element with the internal id 2, we would use the following code:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">\u0275\u0275select(2);\n\u0275\u0275property(\"comicId\", ctx.params.comicId);<\/pre>\n<p>As we have now the necessary knowledge about Ivy's internals, we case build upon it to dynamically create components like out\u00a0<code>RoutedComicComponent<\/code>.<\/p>\n<h2 id=\"creating-a-higher-order-component-dynamic-component\" class=\"code-line\" data-line=\"191\">Creating a higher order component\/ dynamic component<\/h2>\n<p class=\"code-line\" data-line=\"193\">To dynamically create an Ivy component, we just need a factory function which takes parameters and returns the component. In our case, the only parameter is the Angular component we want to route to. To be more precise, it's the inner component's type, e. g.\u00a0<code>ComicComponent<\/code>.<\/p>\n<p class=\"code-line\" data-line=\"195\">The return value is a dynamic routed component which renders the passed component and delegates all received routing parameters. This make this routed component a higher order component as it is a component parameterized with another one.<\/p>\n<p class=\"code-line\" data-line=\"197\">Let's say, the factory function is called\u00a0<code>withRoute<\/code>. In this case we can use it as follows within our routing configuration:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">const routes: Routes = [\n  {\n    path: 'comic\/:comicId',\n    component: withRoute(ComicComponent)\n  }\n];<\/pre>\n<p class=\"code-line\" data-line=\"208\">Because of this, we don't need to handwrite a\u00a0<code>RoutedComicComponent<\/code>\u00a0anymore.<\/p>\n<p class=\"code-line\" data-line=\"210\">The basic structure of such a function looks like this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">export function withRoute(inner: Type&lt;any&gt;) {\n\n    \/\/ Step 1: Create a class on the fly\n    class HigherOrderComponent implements OnInit {\n      [...]\n    }\n\n    \/\/ Step 2: Assign ngComponentDef\n    HigherOrderComponent.ngComponentDef = \u0275\u0275defineComponent({\n      [...],\n      template: function(rf, ctx) { \n        \/\/ Step 2a: Call the inner component\n        [...] \n      }\n    });\n\n    \/\/ Step 3: Return component\n    return HigherOrderComponent;\n}<\/pre>\n<p>Also, at the beginning of this function, we need to get the selector of the passed component so that it can be rendered dynamically later:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">\/\/ At runtime component will be a \u0275ComponentType&lt;any&gt; with\n\/\/ a static ngComponentDef property\nconst ngComponent = inner as \u0275ComponentType&lt;any&gt;;\n\n\/\/ Step 1: Get needed information from ngComponentDef\nconst def = ngComponent.ngComponentDef as \u0275ComponentDef&lt;any&gt;;\n\n\/\/ Simplification: We assume a single element name\nconst elementName = def.selectors[0][0] as string;<\/pre>\n<p>The class declared within the function looks like this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">class HigherOrderComponent implements OnInit {\n\n    static ngComponentDef: \u0275ComponentDef&lt;HigherOrderComponent&gt;;\n\n    params: any = {};\n\n    constructor(private route: ActivatedRoute) {\n    }\n\n    ngOnInit() {\n        this.route.params.subscribe(params =&gt; {\n          this.params = params;\n        });\n    }\n}<\/pre>\n<p class=\"code-line\" data-line=\"268\">As you see here, this method only puts the received routing parameters in the property\u00a0<code>params<\/code>.<\/p>\n<p class=\"code-line\" data-line=\"270\">Please note that each call of the function declares a new class. Technically, you have a local variable\u00a0<code>HigherOrderComponent<\/code>\u00a0pointing to a dynamically created class.<\/p>\n<p class=\"code-line\" data-line=\"272\">The assigned\u00a0<code>ngComponentDef<\/code>\u00a0contains the same information as we've found in the bundle described above:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">HigherOrderComponent.ngComponentDef = \u0275\u0275defineComponent({\n    consts: 1,\n    vars: 1,\n    directives: [\n        component\n    ],\n    changeDetection: ChangeDetectionStrategy.Default,\n    factory: () =&gt; new HigherOrderComponent(\n        \u0275\u0275directiveInject(ActivatedRoute)),\n    selectors: [[]],\n    template: (rf, ctx) =&gt; {\n        [...]\n    },\n    type: HigherOrderComponent,\n});<\/pre>\n<p>To give this component the possibility to render the inner component, the latter one is put into the directives array. However, the real interesting part here is the template function which binds the routing parameters:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">template: (rf, ctx) =&gt; {\n\n    if (rf &amp; \u0275RenderFlags.Create) {\n        \u0275\u0275element(0, elementName);\n    }\n    if (rf &amp; \u0275RenderFlags.Update) {\n        for (const prop in ctx.params) {\n            const compProp = def.inputs[prop];\n            if (compProp) {\n                \u0275\u0275property(prop, ctx.params[compProp]);\n            }\n        }\n    }\n},<\/pre>\n<p class=\"code-line\" data-line=\"311\">Instead of hardcoding the render flags this function uses the\u00a0<code>\u0275RenderFlags<\/code>\u00a0enumeration. During the creation phase, it creates an element for the inner component.<\/p>\n<p class=\"code-line\" data-line=\"313\">During the the update phase, the template function iterates through all received routing parameters and checks if the passed component has inputs with the same name. For this, it looks into the\u00a0<code>inputs<\/code>\u00a0map of its\u00a0<code>ngComponentDef<\/code>.<\/p>\n<p class=\"code-line\" data-line=\"315\">If there is a match, the respective property can be found within this map. In Angular it's usual that inputs have the same name as their properties. In this case the\u00a0<code>inputs<\/code>\u00a0map looks like this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">{\n  \"comicId\": \"comicId\"\n}<\/pre>\n<p>However, the\u00a0<code>Input<\/code>\u00a0decorator gives us the possibility to assign a different name to the inputs using a parameter:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@Input('cid') comicId: string;<\/pre>\n<p>In this case, the\u00a0<code>input<\/code>\u00a0property would map\u00a0<code>cid<\/code>\u00a0to comicId:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">{\n  \"cid\": \"comicId\"\n}<\/pre>\n<p class=\"code-line\" data-line=\"337\">That shows, we are on the safe side when looking the property name up in this map.<\/p>\n<p class=\"code-line\" data-line=\"339\">After finding a match, the template function updates the respective property using\u00a0<code>\u0275\u0275property<\/code>.<\/p>\n<p class=\"code-line\" data-line=\"341\">The result is a function that creates the routed component on the fly. We don't need to handwrite it anymore.<\/p>\n<h2 id=\"conclusion\" class=\"code-line\" data-line=\"343\">Conclusion<\/h2>\n<p class=\"code-line\" data-line=\"345\">Ivy allows us to dynamically create components on the fly and hence to create higher order components. For this, we just need a class with a proper\u00a0<code>ngComponentDef<\/code>\u00a0property.<\/p>\n<p class=\"code-line\" data-line=\"347\">To find out how such a\u00a0<code>ngComponentDef<\/code>\u00a0needs to be structured, we can AOT-compile an example and examine the resulting bundles.<\/p>\n<p class=\"code-line\" data-line=\"349\">While this is really straight forward, please keep in mind that we need to leverage Ivy's private APIs for this. However, enabling such things was a design goal for Ivy and sooner or later the Angular team will (hopefully) add these possibilities to the public API.<\/p>\n<h2 id=\"bonus-compiling-at-runtime\" class=\"code-line\" data-line=\"351\">Bonus: Compiling at runtime<\/h2>\n<p class=\"code-line\" data-line=\"353\"><strong>If performance and bundle sizes do not matter<\/strong>\u00a0and\u00a0<strong>if you are not able to feel any pain at all<\/strong>, you can also use the Angular compiler at runtime:<\/p>\n<p class=\"code-line\" data-line=\"355\">For this, you have to import the compiler somewhere in your application, e. g. when bootstrapping:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">import '@angular\/compiler';<\/pre>\n<p>Then, create your component class on the fly, e. g. within an factory function:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">@Component({ template: '' }) \nclass HigherOrderComponent { [...] }<\/pre>\n<p class=\"code-line\" data-line=\"368\">Please note, that this Decorator is not used at all. However, we need to use an arbitrary decorator to make TypeScript emit the necessary metadata for dependency.<\/p>\n<p class=\"code-line\" data-line=\"370\">To get an\u00a0<code>ngComponentDef<\/code>, call the compiler:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">\u0275compileComponent(HigherOrderComponent, { template: '&lt;b&gt;Hello&lt;\/b&gt;' });<\/pre>\n<p class=\"code-line\" data-line=\"376\">The second parameter takes the traditional options normally passed to @Component. Obviously, you can create this object dynamically.<\/p>\n<p class=\"code-line\" data-line=\"378\">On interesting aspect of\u00a0<code>\u0275compileComponent<\/code>\u00a0is that it works asynchronously if it needs to resolve load files like the template or css files. Otherwise it works synchronously. In the first case, you don't get the\u00a0<code>ngComponentDef<\/code>\u00a0property immediately and hence further operations with this component will fail. To prevent this, call\u00a0<code>\u0275resolveComponentResources<\/code>\u00a0after calling\u00a0<code>\u0275compileComponent<\/code>\u00a0and await the promise returned.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>With Ivy&#8217;s private APIs, we can dynamically create components. The example here demonstrates this by creating a routed component on the fly.<\/p>\n","protected":false},"author":9,"featured_media":3118,"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-3105","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>Architecture with Angular Ivy - Part 2: Higher order and dynamic Components - 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\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Architecture with Angular Ivy - Part 2: Higher order and dynamic Components - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"With Ivy&#039;s private APIs, we can dynamically create components. The example here demonstrates this by creating a routed component on the fly.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2019-08-13T10:22:40+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/matryoshka-2742506-640.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"640\" \/>\n\t<meta property=\"og:image:height\" content=\"426\" \/>\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=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/\"},\"author\":{\"name\":\"Manfred Steyer, GDE\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\"},\"headline\":\"Architecture with Angular Ivy &#8211; Part 2: Higher order and dynamic Components\",\"datePublished\":\"2019-08-13T10:22:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/\"},\"wordCount\":1736,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/matryoshka-2742506-640.jpg\",\"articleSection\":[\"Unkategorisiert\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/\",\"name\":\"Architecture with Angular Ivy - Part 2: Higher order and dynamic Components - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/matryoshka-2742506-640.jpg\",\"datePublished\":\"2019-08-13T10:22:40+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/matryoshka-2742506-640.jpg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/matryoshka-2742506-640.jpg\",\"width\":640,\"height\":426},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Architecture with Angular Ivy &#8211; Part 2: Higher order and dynamic Components\"}]},{\"@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":"Architecture with Angular Ivy - Part 2: Higher order and dynamic Components - 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\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/","og_locale":"en_US","og_type":"article","og_title":"Architecture with Angular Ivy - Part 2: Higher order and dynamic Components - ANGULARarchitects","og_description":"With Ivy's private APIs, we can dynamically create components. The example here demonstrates this by creating a routed component on the fly.","og_url":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/","og_site_name":"ANGULARarchitects","article_published_time":"2019-08-13T10:22:40+00:00","og_image":[{"width":640,"height":426,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/matryoshka-2742506-640.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":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/"},"author":{"name":"Manfred Steyer, GDE","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951"},"headline":"Architecture with Angular Ivy &#8211; Part 2: Higher order and dynamic Components","datePublished":"2019-08-13T10:22:40+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/"},"wordCount":1736,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/matryoshka-2742506-640.jpg","articleSection":["Unkategorisiert"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/","url":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/","name":"Architecture with Angular Ivy - Part 2: Higher order and dynamic Components - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/matryoshka-2742506-640.jpg","datePublished":"2019-08-13T10:22:40+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/matryoshka-2742506-640.jpg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2019\/08\/matryoshka-2742506-640.jpg","width":640,"height":426},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/architecture-with-angular-ivy-part-2-higher-order-and-dynamic-components\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Architecture with Angular Ivy &#8211; Part 2: Higher order and dynamic Components"}]},{"@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\/3105","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=3105"}],"version-history":[{"count":0,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/3105\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/3118"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=3105"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=3105"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=3105"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}