Many Angular developers are asking a question about what is a counterpart of a $compile() function of AngularJs in Angular (2+). In AngularJs you were able to append a string with some HTML markup and AngularJs directives to a template and use $compile() function to generate a fully functional view. In Angular there is no $compile() function, so you need to use other tricks to achieve a similar result.
There are many cases where you would need to generate a view from a string. In one of AngularJs apps I was working on, we had to build a help section with content that can be retrieved from the API and contains HTML markup and a directive for representing mathematical formulas. In this article, you can find out how to show content from a string in AngularJs app and how the same is possible in Angular. To simplify the example, I will be using a simple “welcome” AngularJs directive / Angular component inside a string:
“Welcome” directive/component shows a welcome text with the name which needs to be passed to it. In our example, the name is “John”. Please note that in the string from the example for passing the name to the “welcome” component I used Angular notation, but for AngularJs the only difference would be that “[name]” is not enclosed in brackets.
The expected result is:
In AngularJs we created a directive and named it “dynamic”. It sets HTML content (string) inside the host element and uses a $compile() function to compile directives and filters from the content of the host element to generate a fully functional view.
In Angular, you cannot directly compile a string which contains referenced components. The trick is to create a new component with a dynamic template on the fly, then register that component with a module also generated on the fly and pass generated component and module to the *ngComponentOutlet directive on an element. Let’s show the code first and then walk through it step by step.
Here we have a component called “DemoDynamicContentComponent” which on initialisation starts creating a dynamic component and module in createEmbeddedContent() method. The dynamic component gets generated in createNewComponent() method, and the code looks similar to the way we usually implement components with a @Component decorator, but this time the template of the component is whatever string we pass in there. In the example the string we pass as a template is defined in “dynamicHtmlContent” variable.
Next step is to generate a module on the fly which needs to register previously generated dynamic component. Creation of module looks similar to the way it is usually implemented with @NgModule decorator and metadata. In our dynamic module, we import Angular’s Common module to be able to use common Angular directives as *ngIf, *ngFor, etc. and WelcomeModule to be able to use “app-welcome” component because it is declared in WelcomeModule. We also need to declare our dynamic component in this new module and set the dynamic component in “entryComponents” array.
After the module is created, we compile it using compileModuleSync() function from the “compiler” provider which we have injected in the constructor. Now we only need to put our newly created and registered dynamic component to the template. We do that by passing “dynamicComponent” and “dynamicModule” to the *ngComponentOutlet directive on an element.
From these two examples it can be seen that compiling a string was more straightforward in AngularJs, but when you know how to make dynamic components, it's not that hard to create a reusable component which accepts a string with HTML and Angular references and generate a fully functional view in Angular.