**This post currently reflects an earlier version of Angular, and may not be up to date or reflect the current release. To learn more about about the latest version of Angular and migration, follow the link here **

The Evolution

Creating components has been a topic of interest at Rangle because with each RC version of Angular 2, it seemed like the way to do so had changed.

Near the beginning there was the DynamicComponentLoader .

After that was deprecated, there was ComponentResolver .

And now that the dust has settled, there is the ComponentFactoryResolver !

The (Main) Reason

Why would I ever want to dynamically create a component?

Modals

Imagine throughout your app you have buttons that trigger different modals to open

Some of these modals need to be initialized with some information for their state

And as we know, modals are best kept as children of the body tag to avoid issues

A good solution to this problem would be a modal factory.

The modal factory would:

Be given the component class, representing the modal we want, along with any information it needs

Use this information and create the modal on the fly

Keep reference to the created component and destroy it at some point

The Code / Explanation

Imagine we have a simple component called App that contains two buttons:

One to create a hello world modal component

One to create a world hello modal component

In App we have another component with the selector dynamic-component . This component takes a property called componentData which gives reference to the component we want to create and any information we want to pass down.

It could look something like this:

@ Component ( { selector : 'my-app' , template : ` <div> <h2>Lets dynamically create some components!</h2> <button (click)="createHelloWorldComponent()">Create Hello World</button> <button (click)="createWorldHelloComponent()">Create World Hello</button> </div> <dynamic-component [componentData]="componentData"></dynamic-component> ` , } ) export class App { componentData = null ; createHelloWorldComponent ( ) { this . componentData = { component : HelloWorldComponent , inputs : { showNum : 9 } } ; } createWorldHelloComponent ( ) { this . componentData = { component : WorldHelloComponent , inputs : { showNum : 2 } } ; } }

By clicking on either of the Create Hello World or Create World Hello buttons, the appropriate event will fire, sending data into dynamic-component .

The dynamic-component will now generate the appropriate component using the information given.

Now let's look at how this DynamicComponent would be implemented.

This component will need a few things:

Knowledge of all possible components it will be creating

A place to put a created component

Access to the ComponentFactoryResolver service

A variable to store a created component so we can remove it later

import { Component , ViewContainerRef , ViewChild , ReflectiveInjector , ComponentFactoryResolver } from '@angular/core' ; import HelloWorldComponent from './hello-world-component' ; import WorldHelloComponent from './world-hello-component' ; @ Component ( { selector : 'dynamic-component' , entryComponents : [ HelloWorldComponent , WorldHelloComponent ] , template : ` <div #dynamicComponentContainer></div> ` , } ) export default class DynamicComponent { currentComponent = null ; @ ViewChild ( 'dynamicComponentContainer' , { read : ViewContainerRef } ) dynamicComponentContainer : ViewContainerRef ; constructor ( private resolver : ComponentFactoryResolver ) { } … }

As you can see above, entryComponents is where we inform DynamicComponent of the possible components we want it to create.

We’ve attached a reference to a div in our class so that we can access it and place the component we create inside of it.

We’ve injected the ComponentFactoryResolver into the class.

And lastly, we've created a variable called currentComponent to store the created component.

With all of the setup complete, we’re able to move on to the actual component creation!

Let's implement an Input setter that takes a component class and an object with key/value pairs mapping to what we want access in the created component.

@ Input ( ) set componentData ( data : { component : any , inputs : any } ) { if ( ! data ) { return ; } let inputProviders = Object . keys ( data . inputs ) . map ( ( inputName ) => { return { provide : inputName , useValue : data . inputs [ inputName ] } ; } ) ; let resolvedInputs = ReflectiveInjector . resolve ( inputProviders ) ; let injector = ReflectiveInjector . fromResolvedProviders ( resolvedInputs , this . dynamicComponentContainer . parentInjector ) ; let factory = this . resolver . resolveComponentFactory ( data . component ) ; let component = factory . create ( injector ) ; this . dynamicComponentContainer . insert ( component . hostView ) ; if ( this . currentComponent ) { this . currentComponent . destroy ( ) ; } this . currentComponent = component ; }

The function above does the following:

Turns the inputs into a format Angular 2 can understand

Creates an injector out of the resolved inputs and DynamicComponent injector

injector Creates a factory out of the component we want to create

Creates a component out of the factory and injector

Inserts the component into the placeholder container we created earlier

Destroys the previously created component

And there you have it, we’ve dynamically created a modal!

The Example

Here's a simple Plunker I made demonstrating what was explained above: http://plnkr.co/edit/ZXsIWykqKZi5r75VMtw2?p=preview

More Resources