Summary of what I'm trying to accomplish
- dynamically add components to a
ViewContainerRef(done) - initialized these Dynamic components with properties (done)
- get access to the dynamically created Component instances so that I may make decisions based what is.
the problem
- when adding components dynamically, they are added to a
ViewContainerRef ViewContainerRefoffers methods, such asget(index)that returnViewRef.ViewRefdoesn't appear to have any relationship to theComponentinstance, making it a challenge to obtain the required data
Here is a Stackblitz Link with working code show below (for dynamically creating the components)
the appComponent starts off by creating a few component using ComponentFactoryResolver, and adding them to the ViewChild defined in the template. each DynamicComponent is initialized with an id property value that we are trying to reference after creation
@Component({
selector: "my-app",
template: `
<h3>Retrieving Component Reference for Dyamic Compnents</h3>
<button (click)="getCompRef()">Get References</button>
<div>
<ng-container #childCont></ng-container>
</div>
<div>
<small>List out the Ids from the dynamic components</small> <br />
{{ createdItemIds | json }}
</div>
`,
styleUrls: ["./app.component.css"]
})
export class AppComponent implements AfterViewInit {
@ViewChild("childCont", { read: ViewContainerRef })
childCont: ViewContainerRef;
createdItemIds: string[] = [];
itemLimit = 5;
constructor(
private fr: ComponentFactoryResolver,
private cdr: ChangeDetectorRef
) {}
ngAfterViewInit(): void {
for (let i = 0; i < this.itemLimit; i++) {
const factory = this.fr.resolveComponentFactory(DynamicComponent);
const compRef = this.childCont.createComponent(factory, i);
// Set the id of the instance so that we can use it later
compRef.instance.id = i + 1;
this.cdr.detectChanges();
}
}
...
}
the DynamicComponent being added is fairly simple. for simplifications purposes, it only contains a single id property that we are trying to get at
@Component({
selector: "dynamic-component",
template: `
<div>Dynamic Component: {{ id }}</div>
`,
styles: [``]
]
})
export class DynamicComponent {
id: number;
}
Everything is fine so far.
- The components are dynamically created
- the component instances are initialized with the ID, which we can see by the fat that it is displayed in the UI
the issue comes with trying to retrieve the ID property from the DynamicallyCreated components.
In the AppComponent, when the user clicks the button, the getCompRef() method gets called and loops through each child of the childCont (ViewContainerRef)
getCompRef(): void {
for (let i = 0; i < this.itemLimit; i++) {
const viewRef = this.childCont.get(i);
// How do I get at the instance of the view in order to obtain id?
// the view Ref doesn't provide access to the instance
// console.log(viewRef);
}
}
however the ViewRef returned from ViewContainerRef.get() is an sub class of ChangeDetectoreRef and doesn't hold any reference to the instance in question.
In doing research on this issue, it tried going down the path of using ViewChildren to get the list components being created, but this didn't work because of issues such as
- https://github.com/angular/angular/issues/8785
- or examples assume the directive used in the
ViewChildrenselectoris for a component that has been predefined in a template - I see a lot of question in reference to some folks looking to get the ViewRef when they have the
Component.instance, but that isn't helpful in this situation.
Ultimately my question is,
- is there a simple way to get at the Component instance from a
ViewRefthat I'm missing
Any help is appreciated.
thank you.