RSS

Injecting Components in Runtime

04 ספט

This post explains how to create component in runtime. I will show two scenario:

1.      How to inject a component in runtime without knowing which component will inject until runtime.

2.      How to inject HTML with components in runtime. The HTML will creates in runtime by some logics.

The code is based on Angular 2 RC 6.

Click here for live example.


Demo 1 – Inject component in runtime

The goal:

Injecting components in runtime that have not been loaded or compiled before on the client side.

clip_image002

When we click on the button “Dynamic component (Start)” the application starts add string to the shapes array every second. The string is random form names of shapes (circle, triangle, square and rectangle). Each string converts to component. Only when we click on button the components load and compiles.

Code explanations:

Only the shape-dynamic-loader component (shape.component.ts) needs to be explained, all the others are pretty obvious.

1.      The template of this component is very simple; Placeholder for the shape’s component (circle, square, triangle and rectangle).

        <span #span>span>

 

2.      I use @ViewChild to get a ViewContainerRef of the span element. I will use it for creating the right shape component.

        @ViewChild('span', { read: ViewContainerRef }) span;

 

3.      Every time I set the source input, the createComponent method is executed.

_shape:string;
@Input(
'source'
)
set
shape(value){
this
._shape = value;
this
.createComponent();
}

 

4.      The createComponent method does all the hard work.

createComponent(){
let
injector = ReflectiveInjector
.fromResolvedProviders([],
this
.vcRef.parentInjector);
// 1. Create module loader
let loader = new SystemJsNgModuleLoader(this
.compiler);
loader.load(
'app/shapes/shapes.module'
)
.then((nmf:NgModuleFactory<
any
>)=>{
// 2. create NgModuleRef
let
ngmRef = nmf.create(injector);
let shape = ngmRef.instance.shapes.get(this
._shape);
// 3. Create component factory
let
cmpFactory = ngmRef
.componentFactoryResolver
.resolveComponentFactory( shape );
// 4. Create the component
let componentRef = this.span.createComponent(cmpFactory,0
,injector,[]);
// 5. Init the component name field.

            componentRef.instance.name = this._shape;
// 6. Refresh the component area.

            componentRef.changeDetectorRef.detectChanges();
componentRef.onDestroy(()=> {
componentRef.changeDetectorRef.detach();
});
});
}

 

Demo 2 – Inject HTML with components in runtime

The goal:

Injecting in runtime HTML with components that have not been loaded or compiled before on the client side.

clip_image004

When we click on Dynamic HTML button the application will create HTML string and compile it and add it to the DOM.

Code explanations:

This demo is more complicated because we need to create a HTML on the fly. We need to load the components that exist in the HTML string that we created in runtime.

1.      Create module loader same as the first demo. createDynamicComponentFromHtml method.

2.      Load the modules that have the components that we need, for the HTML. Again, same as first demo.

3.      Create component in runtime that has the HTML.


Capture

As you can see, this is a simple template. Usually we create here dynamic template base on    some logics.

4.      Create a module that imports all the modules I need for the template. After the module is created, I have to compile it.

createDynamicFactory(injector,moduleClass){
@Component({
selector :
'dynamic-html'
,
template :
`…`
})
class
DynamicHtmlComponent{}
@NgModule({
imports        : [moduleClass],
declarations   : [DynamicHtmlComponent],
entryComponents: [DynamicHtmlComponent]
})
class
DynamicModule{}
return this
.compiler
.compileModuleAsync(DynamicModule)
.then((ngMdlFactory)=>{
let
ngMdlRef = ngMdlFactory.create(injector);
// Create component factory
let
cmpFactory = ngMdlRef.componentFactoryResolver
.resolveComponentFactory( DynamicHtmlComponent );

return cmpFactory;
});
}

This method does 3 imported steps:

a.      Compile the module and return NgModuleFactory.

b.      Create NgModuleRef from NgModuleFactory.

c.      Create ComponentFactory from NgModuleRef.

5.      Now that I have ComponentFactory the rest of the code is same as first demo.

this.createDynamicFactory(injector,ngMdlRef.instance.constructor)
.then((cmpF)=>{
// Create the component
let componentRef =  this.span.createComponent(cmpF,0
,injector,[]);
componentRef.changeDetectorRef.detectChanges();
componentRef.onDestroy(()=> {
componentRef.changeDetectorRef.detach();
});
});

 

 

Summary

First demo shows you how we can create a component in runtime. This scenario is good when you don’t know in advance which component you need to use. In our example the list is not homogeneous, I don’t know the shapes until runtime. After the module loaded to the client it will not load again.

Second demo shows you how to create HTML in runtime with components; compile it and inject it.

The demos shows you in action the classes:

1.      SystemJsNgModuleLoader

2.      Compiler

3.      NgModuleFactory

4.      NgModuleRef

5.      ComponentFactory

6.      ViewContainerRef

7.      ChangeDetectorRef

I hope this information is helpful for you; send feedback please :=).

The next course opens on 18 September. For more information click here.

Advertisements
 
השארת תגובה

פורסם ע"י ב- ספטמבר 4, 2016 ב- Angular 2.0

 

כתיבת תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s

 
%d בלוגרים אהבו את זה: