Dynamically Instantiate an Angular Component

Share this video with your friends

Social Share Links

Send Tweet
Published 6 years ago
Updated 5 years ago

In this lesson we learn how to leverage the ComponentFactoryResolver as well as our anchor we defined previously, to dynamically instantiate an Angular component, in our specific case the TabComponent.

We will also learn how to register our dynamic components in the NgModule’s entryComponent property.

Instructor: [00:00] In our example here, we have most of the building blocks, which help us to build actual dynamic components. First of all, here we have a way of defining our template. We then reference the template and pass it along, in this case via some input property to our tab.

[00:16] That's also the tab component itself. The single tab here is ready for being created dynamically because we have already defined here some input properties, which allow us to pass in the template, add data. Then, inside there in the template of our tab component, we actually can use the ng-container.

[00:34] Add template outlet for referencing the template. Add template outlet context for passing in the actual data, which we get from the outside.

[00:43] Also, in our tabs component -- the whole component which groups all of the single tabs in itself -- is ready. What we have done there is, we have an ng-template, where we have attached some dynamic tab anchor.

[00:57] That's an anchor directive, which we reference here, and which allows us then to later get access to the so-called ViewContainerRef, which we will need for then attaching our dynamic components onto it.

[01:08] Let's get started with actually instantiating our component dynamically. First of all, we need to get access to the component factory resolver. We get that injected here in the constructor. Then, further down, we can remove that log file here and start actually using that component factory.

[01:27] Here, we basically create a new factory out of our component, which in this case is basically our tab component, because that's the one which you want to create dynamically.

[01:41] Once we have that, we can get access to that ViewContainerRef by using our anchor because we will then need that ViewContainerRef to actually create the so-called ComponentRef. We use that ViewContainerRef.createcomponent and we pass in our component factory, of course.

[02:05] At this point, we basically have here a component ref instance. Now, to get the actual instance of our tab component, we can do something like componentref.instance.

[02:20] Now, here we have the living instance of our tab component in memory. As you have seen, the tab component has various properties. If we do instance-dot, we see here we have to associate the title, the template, and data context. These are the things which we obviously want to pass from the outside.

[02:36] Let's add here some parameters. Here's the string. We have the template and some data. Now, we can associate them and say, "Tell title equals to title, instance.template is equal to template." Great.

[02:52] Now, we have wired them up. Let's then create some local area for keeping track of our dynamic components. This is useful for later then interacting with a single dynamic component.

[03:08] What we also would like to have is that whenever our tab gets instantiated here and added to our view, it should also get the focus. We can directly use that select tab function. Let's simply pass in the dynamic tab here, which you have just created. Cool.

[03:23] We also need to do some housekeeping here. What you see here is that in the select tab, we have basically our tabs array, which here in our static part gets directly injected here by the content projection. We grab it via the content controller.

[03:38] We have a second array here, which is the dynamic tabs. What we have to do, first of all, is we have to generate here the header sections also for our dynamic tabs. I simply copy and paste this in here. Here, we use the dynamic tabs. Obviously, you could merge those two, so you can avoid some code duplication here. For the purpose of this example, let's just clone it here.

[04:02] Similarly, we also need to do here the same thing when we select a tab. We don't just have to iterate over the tabs, but also the dynamic tabs, and to deactivate them accordingly. Great.

[04:14] Now, we should actually be able to use it and invoke that open tab function from our app component. Let's jump there and start implementing it here.

[04:23] As you can see, the first one here is the title. Let's simply input here dynamic tab. Then we can use the template. If you remember, template has already been defined here by using this view chart and here by referencing this ng-template in our template section of this app component. Let's simply use that one.

[04:43] As a last step, there is the data, which we have to pass in. Here, we can simply use our people array and access the first person.

[04:50] Now, once the browser refreshes, if we click now, "Add new person," you can see that the tab opens dynamically. You can also see here, "Hi, I am Yuri."

Paweł Waszczyński
Paweł Waszczyński
~ 5 years ago

Hi, great course! Got one question: Is there any particular reason why you're using ng-template as ViewContainerRef , and not just regular HTML element like DIV?

Juri Strumpflohner
Juri Strumpflohnerinstructor
~ 5 years ago

Hey. Yes, ng-template allows you to define a piece of HTML, but it is not being rendered actually. The rendering only happens once you pass its reference to some template outlet. A div instead would be immediately be rendered by the browser.

Hope that makes sense.

Paweł Waszczyński
Paweł Waszczyński
~ 5 years ago

Hey. Yes, ng-template allows you to define a piece of HTML, but it is not being rendered actually. The rendering only happens once you pass its reference to some template outlet. A div instead would be immediately be rendered by the browser.

Absolutely, thanks :)

Paweł Waszczyński
Paweł Waszczyński
~ 5 years ago

Ah, sorry, I replied too soon. Ok I understand that app.component HTML has:

    <ng-template let-person="data" #personEdit>
      Hi, I'm {{ person?.name }}.
    </ng-template>

That makes perfect sense. But my question was about

<ng-template dynamicTabAnchor #container></ng-template>

I mean, this ng-template serves as viewContainerRef and is empty at the beginning, so it could be a div. Actually I'm confused why when you add stuff to this ng-template is shows in the browser, because this ng-template it not passed anywhere to outlet?

Markdown supported.
Become a member to join the discussionEnroll Today