Reputation: 3374
I have some code that dynamically adds/removes components to one of my pages. That seems to work fine and I based the method on Rob Wormald's awesome Ng2 Advanced Talk.
Doing things in that standard way looks like this:
@Component({
template: `
<parent-component>
<template #dyn_target></template>
</parent-component>
`
})
export class MyComp {
@ViewChild('dyn_target', {read: ViewContainerRef}) myTarget;
constructor(protected cfr: ComponentFactoryResolver) {}
ngOnInit(): void {
const factory = this.cfr.resolveComponentFactory(DynComp);
const compRef = this.myTarget.createComponent(factory);
}
}
Everything is happy and works. But now my question is how do I do something like this if the target location for the component is an element that is itself inside an *ngIf? I have code that knows when the *ngIf should be showing the new elements, but I don't know how to lookup the ViewContainerRef for the target inside of the *ngIf.
@Component({
template: `
<parent-component>
<other-comp></other-comp>
<div *ngIf="showMe"
<nested-comp>
<template #dyn_target></template>
</nested-comp>
</div>
</parent-component>
`
})
export class MyComp {
@ViewChild('dyn_target', {read: ViewContainerRef}) myTarget;
showMe: boolean = false;
constructor(protected cfr: ComponentFactoryResolver) {}
addDynComponent(): void {
// Q: how do I do this? vv
const target: ViewContainerRef = lookup('dyn_target');
const factory = this.cfr.resolveComponentFactory(DynComp);
const compRef = target.createComponent(factory);
}
}
I thought about trying to remove the ngIf and make the entire block dynamic, but that doesn't really work for my case because most of the content is static, there is just one subcomponent that needs to be added when/if the ngIf is true.
Anyone know how to find a ViewContainerRef on the fly after the ngIf adds the other elements to the DOM?
Note: another way I thought about doing this is to add a new component type that just shows a nested component based upon an input of a component class type. I have seen that type of thing done for Ionic 2 and it would probably work in my case but seems like overkill. So something like:
@Component({
template: `
<parent-component>
<other-comp></other-comp>
<div *ngIf="showMe"
<nested-comp>
<show-comp [compClass]="dynClass"></show-comp>
</nested-comp>
</div>
</parent-component>
`
})
export class MyComp {
dynClass: any;
showMe: boolean = false;
addDynComponent(): void {
dynClass = DynComp;
}
}
Upvotes: 4
Views: 2501
Reputation: 657338
I think this should work
@ViewChildren('dyn_target', {read: ViewContainerRef}) myTarget:QueryList<ViewContainerRef>;
ngAfterViewInit() {
this.myTarget.changes.subscribe(changes => {
if(this.myTarget.toArray().length) {
// myTarget ViewContainerRef available
}
});
}
Upvotes: 6