I am using Angular 17 for a tiny app and I want to open different components (with forms) in a dialog window. The dialog itself is a wrapper which has two buttons, one of them should call a method of that component. I found a solution here: https://stackoverflow.com/a/77283310/2776860
The comments says that it's a bit hacky but I cannot manage to solve it on another way? How can I create the component dynamically?
I want to access the component without this statement because it seems to be a bit hacky. this.ngComponentOutlet['_componentRef'].instance;
My code looks like this:
Caller:
export class AppComponent {
constructor(private _dialog: MatDialog) {
}
openDialogOne() {
const data: DialogData<FormComponent> = {
headline: 'Form One',
component: FormOneComponent,
};
this._dialog.open(DialogWrapperComponent, {
width: '500px',
height: '80vh',
data
});
}
...
<button mat-flat-button color="primary" (click)="openDialogOne()">Dialog Form 1</button>
<button mat-flat-button color="primary" (click)="openDialogTwo()">Dialog Form 2</button>
Wrapper:
@Component({
selector: 'app-dialog-wrapper',
standalone: true,
imports: [
MatDialogContent,
MatDialogActions,
MatButton,
MatDialogClose,
MatDialogTitle,
NgComponentOutlet
],
templateUrl: './dialog-wrapper.component.html',
styleUrl: './dialog-wrapper.component.scss'
})
export class DialogWrapperComponent implements AfterViewInit{
@ViewChild(NgComponentOutlet, { static: false })
ngComponentOutlet!: NgComponentOutlet;
constructor(@Inject(MAT_DIALOG_DATA) public data: DialogData<FormComponent>) {
}
submit(): void {
if (this.ngComponentOutlet) {
const componentInstance: FormComponent = this.ngComponentOutlet['_componentRef'].instance;
componentInstance.submit()
}
}
}
Wrapper HTML:
<h2 mat-dialog-title>{{ data.headline }}</h2>
<mat-dialog-content>
<ng-container *ngComponentOutlet="data.component" ></ng-container>
</mat-dialog-content>
<mat-dialog-actions>
<button
mat-flat-button
mat-dialog-close>
Cancel
</button>
<button
mat-flat-button (click)="submit()">
Install
</button>
</mat-dialog-actions>
Many thanks in advance!
I guess the wrapper only use is to call methods from the child component, you can use the
EventBuspattern usingrxjs subjectto emit and event from wrapper and receive it on the child! Working code below for your reference!CHild component listening for event!
wrapper component emitting the event!
service
Stackblitz Demo