I posted this question before. To briefly summarise; I’m trying to call a function that creates instances of a component using the ComponentFactoryResolver and ViewContainerRef inside of another function that is in a non related component. For specifics refer to the previous question.
However, since then I’ve made a bit of progress and have pinpointed the issue. I’ve changed the AddStatusBoxComponent ts file (the component I’m trying to call the other components function from) from this:
import { Component} from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { MatDialogRef } from '@angular/material/dialog';
import { LiveSummaryComponent } from 'src/app/pages/live-summary/live-summary.component';
@Component({
selector: 'app-add-status-box',
templateUrl: './add-status-box.component.html',
styleUrls: ['./add-status-box.component.css']
})
export class AddStatusBoxComponent
{
public parentRef!: LiveSummaryComponent;
constructor(private form: FormBuilder, private dialogRef: MatDialogRef<AddStatusBoxComponent>) {}
addStatusBox()
{
this.parentRef.createComponent();
this.dialogRef.close();
}
}
to this:
import { Component} from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { MatDialogRef } from '@angular/material/dialog';
import { LiveSummaryComponent } from 'src/app/pages/live-summary/live-summary.component';
@Component({
selector: 'app-add-status-box',
templateUrl: './add-status-box.component.html',
styleUrls: ['./add-status-box.component.css']
})
export class AddStatusBoxComponent
{
//public parentRef!: LiveSummaryComponent;
constructor(public parentRef: LiveSummaryComponent, private form: FormBuilder, private dialogRef: MatDialogRef<AddStatusBoxComponent>) {}
addStatusBox()
{
this.parentRef.createComponent();
this.dialogRef.close();
}
}
where I’ve injected the LiveSummaryComponent into the constructor and added it to the providers in app.module.ts
instead. With this I’m able to call the LiveSummaryComponent createComponent()
function, and it works because I tested it by commenting out everything in that function and putting a simple console.log()
to confirm it works.
However when I uncomment the normal contents of the createComponent(
) function and call it from the AddStatusBoxComponent it now gives me a different error message in the browser console:
ERROR TypeError: Cannot read properties of undefined (reading 'createComponent')
at LiveSummaryComponent.createComponent (live-summary.component.ts:52:38)
at AddStatusBoxComponent.addStatusBox (add-status-box.component.ts:129:20)
at AddStatusBoxComponent_Template_form_ngSubmit_3_listener (add-status-box.component.html:4:54)
at executeListenerWithErrorHandling (core.js:15285:1)
at Object.wrapListenerIn_markDirtyAndPreventDefault [as next] (core.js:15323:1)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:183:1)
at SafeSubscriber.next (Subscriber.js:122:1)
at Subscriber._next (Subscriber.js:72:1)
at Subscriber.next (Subscriber.js:49:1)
at EventEmitter_.next (Subject.js:39:1)
This indicates that it’s line 52 in the LiveSummaryComponent which is this line that resides in the createComponent()
function:
let childComponentRef = this.VCR.createComponent(componentFactory);
this.VCR is a ViewContainerRef
that is defined as:
@ViewChild("viewContainerRef", { read: ViewContainerRef })
public VCR!: ViewContainerRef;
I’ve had to use ! Else I get this error:
Property 'VCR' has no initializer and is not definitely assigned in the constructor.
The @ViewChild
I think comes from this in the LiveSummaryComponent template file:
<button type="button" (click)="createComponent()">
I am Parent, Click to create Child
</button>
<ng-template #viewContainerRef></ng-template>
I know it might be confusing that both the LiveSummaryComponent createComponent()
function has the same name as the this.VCR.createComponent(componentFactory);
But they are different functions.
So I think the issue lies here, but I have no idea how to resolve it, so that I’m able to execute the LiveSummaryComponent createComponent()
function inside the AddStatusBoxComponent addStatusBox()
function at the click of a button.
The full code can be found in the previous question, with the only difference this time being my changes to how the LiveSummaryComponent is referenced in the AddStatusBoxComponent via dependency injection in the constructor.
I'm still new to Angular so lot of this I don't really understand properly.
Summary of what I want to achieve:
What I'm trying to achieve is to create instances of a child component (StatusBoxComponent) within a parent (LiveSummaryComponent) but the function createComponent()
that creates instances of StatusBoxComponent that resides in LiveSummaryComponent is called from a completely different component (AddStatusBoxComponent) which pops up as a modal dialogue when a button is pressed on a HeaderCaomponent But I can't access the LiveSummaryComponent createComponent()
function from the AddStatusBoxComponent due the error I highlighted in the question
You could use a Service
to achieve the communication of the event instead of trying to use the createComponent
method that's inside the component directly.
See this StackBlitz demo.
Note that this is in Angular v14, so I had to comment out a line regarding the dynamic component creation.
Also, I am not using an actual modal. But if you adjust the code, this should work in your case in exactly the same way.