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
ViewContainerRef
offers methods, such asget(index)
that returnViewRef
.ViewRef
doesn't appear to have any relationship to theComponent
instance, 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
ViewChildren
selector
is 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
ViewRef
that I'm missing
Any help is appreciated.
thank you.
I could only do this by keeping track of the instances of these components in a different array.