Reputation: 461
I would like to create a ViewRef from markup that is dynamically inserted into a template. Is this possible based on the following code sample?
template.html:
<ng-container *ngTemplateOutlet="dynamic; context: cntx"></ng-container>
<ng-template #dynamic>
<div [innerHTML]="markup"></div>
</ng-template>
Injected markup from API call to bind to div's innerHTML attribute:
<div>
<div id="forViewRef"></div>
</div>
component.ts:
@ContentChild('#forViewRef', { read: ViewContainerRef }): someHndl;
private _nativeElem: any;
constructor(
private sanitizer: DomSanitizer,
private _vcRef: ViewContainerRef,
private _resolver: ComponentFactoryResolver) {
// to ensure template has been created, #dynamic
this._nativeElem = this._vcRef.element.nativeElement;
}
// listen to lifecycle hook
ngAfterContentChecked() {
if (this._nativeElem !== undefined)
// childContent ref is undefined
console.log(this.someHndl);
// markup is in the DOM
console.log(this._nativeElem.querySelectorAll('#forViewRef'));
}
Upvotes: 0
Views: 4333
Reputation: 214175
To create component dynamically inside <div id="forViewRef"></div>
you can do the following:
Let's say we need to load the following component
@Component({
selector: 'dynamic-comp',
template: `
<h2>Dynamic component</h2>
<button (click)="counter = counter + 1">+</button> {{ counter }}
`
})
export class DynamicComponent {
counter = 1;
}
so first add it to declarations
and entryComponents
array of your @NgModule
...
declarations: [ ..., DynamicComponent ],
entryComponents: [ DynamicComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
after that create
template.html
<button (click)="createComponent()">Create component</button>
<div id="forViewRef"></div>
and finally write
component.ts
export class AppComponent {
compRef: ComponentRef<DynamicComponent>;
constructor(private injector: Injector,
private resolver: ComponentFactoryResolver,
private appRef: ApplicationRef) {}
createComponent() {
const compFactory = this.resolver.resolveComponentFactory(DynamicComponent);
this.compRef = compFactory.create(this.injector, null, '#forViewRef');
this.appRef.attachView(this.compRef.hostView);
}
ngOnDestroy() {
if(this.compRef) {
this.compRef.destroy();
}
}
}
I use appRef.attachView
in order to include dynamic component to change detection cycle
See also
Upvotes: 3