{ "id": "guide/dynamic-component-loader", "title": "Dynamic component loader", "contents": "\n\n\n
Component templates are not always fixed. An application may need to load new components at runtime.
\nThis cookbook shows you how to use ComponentFactoryResolver
to add components dynamically.
See the
The following example shows how to build a dynamic ad banner.
\nThe hero agency is planning an ad campaign with several different\nads cycling through the banner. New ad components are added\nfrequently by several different teams. This makes it impractical\nto use a template with a static component structure.
\nInstead, you need a way to load a new component without a fixed\nreference to the component in the ad banner's template.
\nAngular comes with its own API for loading components dynamically.
\n\nBefore you can add components you have to define an anchor point\nto tell Angular where to insert components.
\nThe ad banner uses a helper directive called AdDirective
to\nmark valid insertion points in the template.
AdDirective
injects ViewContainerRef
to gain access to the view\ncontainer of the element that will host the dynamically added component.
In the @Directive
decorator, notice the selector name, adHost
;\nthat's what you use to apply the directive to the element.\nThe next section shows you how.
Most of the ad banner implementation is in ad-banner.component.ts
.\nTo keep things simple in this example, the HTML is in the @Component
\ndecorator's template
property as a template string.
The <ng-template>
element is where you apply the directive you just made.\nTo apply the AdDirective
, recall the selector from ad.directive.ts
,\n[adHost]
. Apply that to <ng-template>
without the square brackets. Now Angular knows\nwhere to dynamically load components.
The <ng-template>
element is a good choice for dynamic components\nbecause it doesn't render any additional output.
Take a closer look at the methods in ad-banner.component.ts
.
AdBannerComponent
takes an array of AdItem
objects as input,\nwhich ultimately comes from AdService
. AdItem
objects specify\nthe type of component to load and any data to bind to the\ncomponent.AdService
returns the actual ads making up the ad campaign.
Passing an array of components to AdBannerComponent
allows for a\ndynamic list of ads without static elements in the template.
With its getAds()
method, AdBannerComponent
cycles through the array of AdItems
\nand loads a new component every 3 seconds by calling loadComponent()
.
The loadComponent()
method is doing a lot of the heavy lifting here.\nTake it step by step. First, it picks an ad.
How loadComponent() chooses an ad
\nThe loadComponent()
method chooses an ad using some math.
First, it sets the currentAdIndex
by taking whatever it\ncurrently is plus one, dividing that by the length of the AdItem
array, and\nusing the remainder as the new currentAdIndex
value. Then, it uses that\nvalue to select an adItem
from the array.
After loadComponent()
selects an ad, it uses ComponentFactoryResolver
\nto resolve a ComponentFactory
for each specific component.\nThe ComponentFactory
then creates an instance of each component.
Next, you're targeting the viewContainerRef
that\nexists on this specific instance of the component. How do you know it's\nthis specific instance? Because it's referring to adHost
and adHost
is the\ndirective you set up earlier to tell Angular where to insert dynamic components.
As you may recall, AdDirective
injects ViewContainerRef
into its constructor.\nThis is how the directive accesses the element that you want to use to host the dynamic component.
To add the component to the template, you call createComponent()
on ViewContainerRef
.
The createComponent()
method returns a reference to the loaded component.\nUse that reference to interact with the component by assigning to its properties or calling its methods.
In the ad banner, all components implement a common AdComponent
interface to\nstandardize the API for passing data to the components.
Here are two sample components and the AdComponent
interface for reference:
The final ad banner looks like this:
\nSee the