Introduction:
You can create a component in angular on the fly, isn’t it amazing, yes it is.
Let me explain it by an example. Suppose that you want to create an Angular studio in which you provide some list of built-in components to the user and a playground.
Now the user wants to create a form with two inputs fields and a button. Since Angular studio has the input field and buttons in its built-in components list, the user will drag the component from the available list into the playground.
Now we are hitting a challenge here, we need to compile and create these dragged components at the runtime.
Compile and create Angular component at runtime:
We can create an Angular component at runtime, apply the decorator to it, and then compile it.
Please follow the following steps:
Step 1: Create a project.
Create an Angular project. If you have an existing one, you can start a direct experiment on it.
ng new DynamicComponentExample –style=scss
Note: –style=scss is optional. I have added it since I want to use sass(Syntactically Awesome Style Sheets).
Step 2: Run the project.
Go to the project directory, install the required packages, and run the project.
Follow the command given below to perform step 2 actions.
cd DynamicComponentExample. (To move into the project directory.)
npm install (To install the required packages.)
ng serve (To build and run the project.)
Now open your browser at the following URL.
http://localhost:4200/
Step 3: Add the HTML for dynamic component.
Update the src/app/app.component.html file. Remove the existing code from that file and add the following code into it.
<div class=”dynamic-code-container” #dcc></div>
Note: #dcc in the HTML code is a template reference variable. It is used to give reference to a DOM element.
Step 4: Add the typescript code.
Add the following code in the src/app/app.component.ts file.
import { Component, ViewChild, ViewContainerRef, Compiler, AfterViewInit, NgModuleRef, NgModule, Injector } from '@angular/core';
import '@angular/compiler';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit {
@ViewChild('dcc', {read: ViewContainerRef}) dcc: ViewContainerRef;
constructor(private compiler: Compiler, private injector: Injector, private moduleRef: NgModuleRef<any>) {}
ngAfterViewInit() {
const html = '<p>{{componentName}} is created and compiled at the run time.</p>';
const dynamicComponent = Component({template: html})(class DynamicComponent {});
const dynamicComponentModule = NgModule({declarations: [dynamicComponent], imports: []})(class {
});
this.compiler.compileModuleAndAllComponentsAsync(dynamicComponentModule)
.then((factories) => {
const factory = factories.componentFactories[0];
const componentRef = factory.create(this.injector, [], null, this.moduleRef);
componentRef.instance.componentName = 'Dynamic Component';
this.dcc.clear();
this.dcc.insert(componentRef.hostView);
});
}
}
Explanation: We are creating and compiling the dynamic component in the ngAfterViewInit() function.
We have defined an HTML template and passed it into the component decorator and decorated it with a class decorator.
In the next step, we have defined a module, added the dynamic component to declarations of the module, and decorated it with a class.
After that, we have used the component factory resolver to create and compile the component at the run time.
Conclusion:
I hope now you have a better understanding of creating and compiling the Angular component at the run time.
To understand how things are working behind the scene, you should be familiar with the concept of decorator and factory resolver i.e. how the decorators and component factory resolver works.
Following is the running example of dynamic component.