Creating Components Dynamically with Component Factory in Angular - InterWorks

Creating Components Dynamically with Component Factory in Angular

Components are the very basic UI building blocks in an Angular app. As we develop an application, sometimes we realize that not all of the components should be fixed. The application may need some of the components to be dynamic.

What we mean by dynamic is the component’s location in the application not to be defined at buildtime meaning it will not be used in any angular template. Instead, the component is instantiated and placed in the application at runtime.

In this article, we will show a simple example of creating components in an Angular app dynamically.

Sample app description

The application that we have used in our article shows the latest news updates. Each new post is shown and rendered after the button Next is clicked. Only one post is shown in the application.

Creating news directive

Before we create any component, we have to create the news directive that will tell the Angular app where to insert components. These are Angular basics, so we will skip them and go straight to the code example of the directive.

In the code above, we can see that NewsDirective injects ViewContainerRef. This is used for the directive to gain access to the view container that will have the dynamically added component.

Creating components

The main component in our example is the NewsComponent, and most of the work will be done there.

In addition, since we are not paying much attention to the design of the application, we will keep things very simple and we’ll add the HTML inside the component’s decorator template as following:

We can see that we actually have a title of the application (“Latest news”) and a button that will trigger the rendering of the new post whenever is clicked.
Also, if we look closely, we’ll see that <ng-template> is using the NewsDirective (newsHost) that we’ve already created.

Component’s structure, step by step

Since we’ve created the HTML for the main page of listing news, we’ve bound the directive with it and now our component gave access to the NewsDirective, we can take a look at the rest of the code.

The first thing that we see  here is that the NewsComponent has an array of NewsItem object as @Input. That array comes from the NewsService that actually only returns all news posts.

By passing all of the news posts, we can allow the component to dynamically list the news posts without having any static elements in the component.

The button that we’ve mentioned above, has the ability to getNews() whenever is being clicked. That method is actually looping through the newsItem array by calling the loadComponent method. The loadComponent method has almost all of the work done inside of it. With that being said, we’ll take a closer look and go through it step by step.

First, we are taking one news post. Then, with componentFactoryResolver, we are resolving ComponentFactory for each component. After that, we are creating an instance of that component.

But, what is actually a ComponentFactory?

If we go by the Angular definition, a ComponentFactory is a base class for a factory that can create a component dynamically. Instantiate a factory for a given type of component with resolveComponentFactory(). Use the resulting ComponentFactory.create() method to create a component of that type.

Let’s get back to the loadComponent method. After the instance of the component is created, we target the viewContainerRef that has the specific instance of the component. Through the NewsDirective that has the ViewContainerRef into its constructor, we access the element that we want to use to host the dynamic component.

The last step will be to add the component to the template. We do that by calling the createComponent method on the viewContainerRef which returns a reference to the loaded component.

NewsComponent Interface

Each component is using the same interface to standardize the API for passing the data:

News app – the final look

This is the final result of this simple news app.

As we can see with the inspect element tool of our browser, only one news post at a time is being rendered.

If we combine this with lazy loading, we can actually reduce the main bundle size of the app and make the user experience better and much faster.

If you liked our blog post, and if you are interested in learning more about it, contact us.

References: https://angular.io/api/core/ComponentFactory


Hristina Avramovska
Hristina Avramovska

Technical Consultant