⚠️ This lesson is retired and might contain outdated information.

Generate Angular 2 Components Programmatically with entryComponents

John Lindquist
InstructorJohn Lindquist
Share this video with your friends

Social Share Links

Send Tweet
Published 8 years ago
Updated 2 months ago

You can generate Angular 2 components using a combination of ViewContainer and ComponentFactory, but you must always remember to add the components you want to generate to your list of entryComponents otherwise the compiler will optimize the component class out of your project.

[00:00] Our home component can actually add this widget3 dynamically. To do that, we need an element with a ref on it. We'll call this ref Container, and this gives us the way to look it up using ViewChild. So, ViewChild, and we'll look it up by that string of "container," call this container, and make sure to import ViewChild.

[00:21] Now in ngAfterContentInit...AfterContentInIt, again, is the one where the ng content has been rendered, so you have access to everything inside of the template and can add things before ngAfterViewInIt fires. With this container...let's just log it out and look at what it is. Let's save.

[00:42] I'll open up the dev tools, and you'll see this is an ElementRef, and to be able to add something to it, right now we just have the native element, so that would do the native-type stuff. But we want what's called a ViewContainerRef, and we can get that by saying we want to read, so read this as a ViewContainerRef. Meaning, instead of reading this as that ElementRef, now it's going to read it as a ViewContainerRef. It's just configuration step.

[01:10] If I open up the dev tools again, now we have a ViewContainerRef, which has some methods on it, like this.container.createComponent. CreateComponent takes what's called a component factory. To create the component, we need to pass a ComponentFactory into here.

[01:30] You get component factories by injecting the ComponentFactory Resolver service, so ComponentFactory Resolver. With this Resolver, this ComponentFactory Resolver, we can say thisResolver.resolve ComponentFactory, and then look it up by the type.

[01:52] We'll look it up by Widget3. Let's make this a bit more readable. We'll say const WidgetFactory is the resolver, Resolve ComponentFactory Widget3, and pass in the WidgetFactory. This actually isn't going to work and the dev tools will show that. This'll explode on me, saying that it cannot find ComponentFactory for Widget 3.

[02:16] That's because, by default, Angular and the Angular compiler are not going to include that compiled side of the components that aren't referenced by selector in the templates. By default, it's going to look up its selector, and only then bundle it. Then it's going to discard any other components that you defined.

[02:34] Even though in Widgets module we declared these and exported them, that simply means, if a selector is used, so before we had Widget3, if this selector is there, then bundle Widget3 inside of there. But it would have discarded Widget1 and Widget 2, because, even though they're exported, they're not being used in a selector somewhere so it would seriously save on the bundle size.

[03:00] Basically, if you want to hard code and make sure that the compiler includes the components you want, there is something called entry components, and you can add Widget3 there. This is saying that somewhere in my code I am definitely going to use Widget3. This is usually with the createComponent and the component resolver.

[03:21] As you can see, we referenced it here. Somewhere in my code, I'm going to use this, so please, please, please don't get rid of this. Compile it in, and let me use it as a component. From here, there are no more errors. You can see that no errors thrown, and we simply have out inputs.

[03:39] Right now, we actually have the input being added here, and that second input, let's delete that one. You'll see this is just one input, and I can type in there. I can actually just create a whole bunch of these guys, hit save, and then it'll add all these different widget factories.

[03:53] Each widget factory will create a new instance of this component when you invoke CreateComponent, so you've got a whole bunch of Widget3s on the page that were provided by the widget factory, created by the ViewContainerRef, and that widget factory was found by resolving ComponentFactory, as long as you defined it in your entry components.

Nicolas
Nicolas
~ 8 years ago

Would love Angular2 CheetSheets! Any plans for this in the future? It's hard to remember everything...

AlankarKumar
AlankarKumar
~ 4 years ago

I wasn't able to create the component in the ngAfterContentInit() lifecycle hook rather had to use ngAfterViewInit()

Markdown supported.
Become a member to join the discussionEnroll Today