0

I'm using angular 2.1 and want to dynamically import a template witch is a string from the backend.

I already use ComponentFactoryResolver to load dynamically my parent container, now I need to create his content witch can look like this:

<my-component>
    <my-nested-component>
    <my-nested-component>
<my-component>

Components are already in my applications, I just need to create them from the template string and load them into the parent.

If create components from string template is not possible, is it possible to do it with lazy loading components ? I see lazy loading with the router but here I under a route and want lazy loading on some composent only

Is it possible ? I know it was possible with angular 2 beta or RC by doing this https://stackoverflow.com/a/39044539/541867

PS: if you want to know why I need to have a template as string coming from the backend it's because the UI of some component is coming from external plugin, they just use a set of component available is the application but can do the layout they want so I can't have it under a @Component template.

EDIT: here is a gist of a first string template I try to load: https://gist.github.com/jaumard/918dfc573b01263467e89adc8ad86f77

2
  • I'm not sure if I got it right, but you can store a string in variable and use *ngIf when there is no milions of them... what I mean is <my-component><my nested-component *ngIf="string == 'nested'"></my-component> OR if you have a lot of these components you can store them in an array and use *ngFor. I know it might not be professional, but it worked when I was working on something similar. Commented Nov 20, 2016 at 10:24
  • I added a gist of what my first template string look like (but there will be much more and much different ones in the future) I don't think it will work the way you said. Am I wrong ? Commented Nov 20, 2016 at 11:14

2 Answers 2

1

If you inject your template in the innerHtml attribute and use the DomSanitizer, it will translate it just like a component, giving you the lazy load effect.

<div [innerHTML]="myComponentsTemplate"></div>

Sign up to request clarification or add additional context in comments.

Comments

0

Turning strings into components after a component is loaded is blocked for security reasons. [https://angular.io/guide/security]

Constructing a dynamic template service seems to be best practice. Sending in values from the server that would be set into a base class, I think can provide what you are trying to do.

There is an offline template compiler, (https://angular.io/guide/security#offline-template-compiler) An example that shows dynamic component creations is exampled in https://angular.io/guide/dynamic-form#dynamic-template.

I think it this just requires a small bit of refactoring the approach to having a dynamic component, and it is referred to as best practice.

To answer, how to translate a string into a component you need to bypass the security with bypassSecurityTrustHtml(). I prefer using pipes for this. https://angular.io/guide/security#bypass-security-apis

I found this one in a forum https://forum.ionicframework.com/t/inserting-html-via-angular-2-use-of-domsanitizationservice-bypasssecuritytrusthtml/62562/2

import {Pipe, PipeTransform} from '@angular/core';
import {DomSanitizer, SafeHtml, SafeStyle, SafeScript, SafeUrl, SafeResourceUrl } from '@angular/platform-browser';

@Pipe({
    name: 'safe'
})
export class SafePipe implements PipeTransform {

constructor(protected _sanitizer: DomSanitizer) {

}

    public transform(value: string, type: string = 'html'): SafeHtml |  SafeStyle | SafeScript | SafeUrl | SafeResourceUrl {
    switch (type) {
        case 'html': return     this._sanitizer.bypassSecurityTrustHtml(value);
        case 'style': return this._sanitizer.bypassSecurityTrustStyle(value);
        case 'script': return this._sanitizer.bypassSecurityTrustScript(value);
        case 'url': return this._sanitizer.bypassSecurityTrustUrl(value);
        case 'resourceUrl': return this._sanitizer.bypassSecurityTrustResourceUrl(value);
        default: throw new Error(`Invalid safe type specified:     ${type}`);
    }
}

}

To implement just use <component-container [innerHtml]='this.safteyPipe.transform(TemplateComponentString)'></component-container>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.