+ `
+})
+export class HeroProfileComponent implements AdComponent {
+ @Input() data: any;
+}
+
+
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/app/main.ts b/public/docs/_examples/cb-dynamic-component-loader/ts/app/main.ts
new file mode 100644
index 0000000000..bc69d2bd33
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/app/main.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
+
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/example-config.json b/public/docs/_examples/cb-dynamic-component-loader/ts/example-config.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/index.html b/public/docs/_examples/cb-dynamic-component-loader/ts/index.html
new file mode 100644
index 0000000000..45529915c2
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ Dynamic Component Loader
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading app...
+
+
+
diff --git a/public/docs/_examples/cb-dynamic-component-loader/ts/sample.css b/public/docs/_examples/cb-dynamic-component-loader/ts/sample.css
new file mode 100644
index 0000000000..7a2ca1f2dc
--- /dev/null
+++ b/public/docs/_examples/cb-dynamic-component-loader/ts/sample.css
@@ -0,0 +1,23 @@
+.hero-profile {
+ border: 1px solid gray;
+ padding: 5px;
+ padding-bottom: 20px;
+ padding-left: 20px;
+ border-radius: 10px;
+ background-color: lightgreen;
+ color: black;
+}
+
+.job-ad {
+ border: 1px solid gray;
+ padding: 5px;
+ padding-bottom: 20px;
+ padding-left: 20px;
+ border-radius: 10px;
+ background-color: lightblue;
+ color: black;
+}
+
+.ad-banner {
+ width: 400px;
+}
\ No newline at end of file
diff --git a/public/docs/ts/latest/cookbook/_data.json b/public/docs/ts/latest/cookbook/_data.json
index 82f126f85b..e7ffea0ace 100644
--- a/public/docs/ts/latest/cookbook/_data.json
+++ b/public/docs/ts/latest/cookbook/_data.json
@@ -36,6 +36,11 @@
"intro": "Techniques for Dependency Injection"
},
+ "dynamic-component-loader": {
+ "title": "Dynamic Component Loader",
+ "intro": "Load components dynamically"
+ },
+
"dynamic-form": {
"title": "Dynamic Forms",
"intro": "Render dynamic forms with FormGroup"
diff --git a/public/docs/ts/latest/cookbook/dynamic-component-loader.jade b/public/docs/ts/latest/cookbook/dynamic-component-loader.jade
new file mode 100644
index 0000000000..d6a35e56c2
--- /dev/null
+++ b/public/docs/ts/latest/cookbook/dynamic-component-loader.jade
@@ -0,0 +1,121 @@
+include ../_util-fns
+
+:marked
+ Component templates are not always fixed. An application may need to load new components at runtime.
+
+ In this cookbook we show how to use `ComponentFactoryResolver` to add components dynamically.
+
+
+:marked
+ ## Table of contents
+
+ [Dynamic Component Loading](#dynamic-loading)
+
+ [Where to load the component](#where-to-load)
+
+ [Loading components](#loading-components)
+
+.l-main-section
+
+:marked
+ ## Dynamic Component Loading
+
+ The following example shows how to build a dynamic ad banner.
+
+ The hero agency is planning an ad campaign with several different ads cycling through the banner.
+
+ New ad components are added frequently by several different teams. This makes it impractical to use a template with a static component structure.
+
+ Instead we need a way to load a new component without a fixed reference to the component in the ad banner's template.
+
+ Angular comes with its own API for loading components dynamically. In the following sections you will learn how to use it.
+
+
+.l-main-section
+
+:marked
+ ## Where to load the component
+
+ Before components can be added we have to define an anchor point to mark where components can be inserted dynamically.
+
+ The ad banner uses a helper directive called `AdDirective` to mark valid insertion points in the template.
+
++makeExample('cb-dynamic-component-loader/ts/app/ad.directive.ts',null,'app/ad.directive.ts')(format='.')
+
+:marked
+ `AdDirective` injects `ViewContainerRef` to gain access to the view container of the element that will become the host of the dynamically added component.
+
+.l-main-section
+
+:marked
+ ## Loading components
+
+ The next step is to implement the ad banner. Most of the implementation is in `AdBannerComponent`.
+
+ We start by adding a `template` element with the `AdDirective` directive applied.
+
++makeTabs(
+ `cb-dynamic-component-loader/ts/app/ad-banner.component.ts,
+ cb-dynamic-component-loader/ts/app/ad.service.ts,
+ cb-dynamic-component-loader/ts/app/ad-item.ts,
+ cb-dynamic-component-loader/ts/app/app.module.ts,
+ cb-dynamic-component-loader/ts/app/app.component.ts`,
+ null,
+ `ad-banner.component.ts,
+ ad.service.ts,
+ ad-item.ts,
+ app.module.ts,
+ app.component`
+)
+
+:marked
+ The `template` element decorated with the `ad-host` directive marks where dynamically loaded components will be added.
+
+ Using a `template` element is recommended since it doesn't render any additional output.
+
++makeExample('cb-dynamic-component-loader/ts/app/ad-banner.component.ts', 'ad-host' ,'app/ad-banner.component.ts (template)')(format='.')
+
+:marked
+ ### Resolving Components
+
+ `AdBanner` takes an array of `AdItem` objects as input. `AdItem` objects specify the type of component to load and any data to bind to the component.
+
+ The ad components making up the ad campaign are returned from `AdService`.
+
+ Passing an array of components to `AdBannerComponent` allows for a dynamic list of ads without static elements in the template.
+
+ `AdBannerComponent` cycles through the array of `AdItems` and loads the corresponding components on an interval. Every 3 seconds a new component is loaded.
+
+ `ComponentFactoryResolver` is used to resolve a `ComponentFactory` for each specific component. The component factory is need to create an instance of the component.
+
+ `ComponentFactories` are generated by the Angular compiler.
+
+ Generally the compiler will generate a component factory for any component referenced in a template.
+
+ With dynamically loaded components there are no selector references in the templates since components are loaded at runtime. In order to ensure that the compiler will still generate a factory, dynamically loaded components have to be added to their `NgModule`'s `entryComponents` array.
+
++makeExample('cb-dynamic-component-loader/ts/app/app.module.ts', 'entry-components' ,'app/app.module.ts (entry components)')(format='.')
+
+:marked
+ Components are added to the template by calling `createComponent` on the `ViewContainerRef` reference.
+
+ `createComponent` returns a reference to the loaded component. The component reference can be used to pass input data or call methods to interact with the component.
+
+ In the Ad banner, all components implement a common `AdComponent` interface to standardize the api for passing data to the components.
+
+ Two sample components and the `AdComponent` interface are shown below:
+
++makeTabs(
+ `cb-dynamic-component-loader/ts/app/hero-job-ad.component.ts,
+ cb-dynamic-component-loader/ts/app/hero-profile.component.ts,
+ cb-dynamic-component-loader/ts/app/ad.component.ts`,
+ null,
+ `hero-job-ad.component.ts,
+ hero-profile.component.ts,
+ ad.component.ts`
+)
+
+:marked
+ The final ad banner looks like this:
+figure.image-display
+ img(src="/resources/images/cookbooks/dynamic-component-loader/ads.gif" alt="Ads")
\ No newline at end of file
diff --git a/public/resources/images/cookbooks/dynamic-component-loader/ads.gif b/public/resources/images/cookbooks/dynamic-component-loader/ads.gif
new file mode 100644
index 0000000000..f7a990fb11
Binary files /dev/null and b/public/resources/images/cookbooks/dynamic-component-loader/ads.gif differ