I want to get the innerHTML of ng-template to my component. Something like
HTML
<my-comp [template]="myTemplate"></my-comp>
<ng-template #myTemplate></ng-template>
TS
export class MyComponent implements OnInit {
@Input() template: string | TemplateRef<any>;
ngOnInit(){
console.log(this.template);
}
}
To access the above ng-template in the component or directive, first, we need to assign a template reference variable. #sayHelloTemplate is that variable in the code below. Now, we can use the ViewChild query to inject the sayHelloTemplate into our component as an instance of the class TemplateRef .
In order to have a template rendered in that container, we use the *ngTemplateOutlet to pass a reference to an existing template, such as the one we created earlier. We use @Input to pass a TemplateRef to our component.
ng-template is an Angular element that is used for rendering HTML in a template. However, it is not rendered directly on DOM. If you include an ng-template tag to a template, the tag and the content inside it will be replaced by comment upon render.
To sum up, ng-content is used to display children in a template, ng-container is used as a non-rendered container to avoid having to add a span or a div, and ng-template allows you to group some content that is not rendered directly but can be used in other places of your template or you code.
Since you only require a shell into which a template will be injected, consider using a Directive instead of a component.
@Directive({
selector: '[template-host]'
})
export class HostDirective{
@Input('template-host') set templateHtml(value){
this.hostElement.innerHTML = value;
}
private hostElement:HTMLElement;
constructor(elementRef:ElementRef){
this.hostElement = elementRef.nativeElement;
}
}
Now you can apply that directive to any element, and the provided template-host
binding will cause html injection in that element. For example:
<!-- The div will contain the html in myTemplate -->
<div [template-host]="myTemplate"></div>
Live demo
If your class actually has a template, but you want to inject html into only a portion of that template, learn about transclusion
I needed to solve exactly the same problem today and found this question. I ended up looking into ng-bootstrap in order to see how they did it, and ultimately it's a fairly simple solution.
You need to get hold of ViewContainerRef that you want your string/TemplateRef to be inserted to. This can be either the host element (ViewContainerRef injected in constructor) or ViewChild. e.g:
constructor(private viewContainerRef: ViewContainerRef) { }
or
@ViewChild('someDiv', {read: ViewContainerRef}) viewContainerRef: ViewContainerRef;
next, in ngOnInit() you need to do an if/else depending if the input is TemplateRef or string and assign it to viewContainerRef:
if (this.template instanceof TemplateRef) {
this.viewContainerRef.createEmbeddedView(<TemplateRef<any>>this.template);
} else {
this.viewContainerRef.element.nativeElement.innerHTML = this.template;
}
Hope that helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With