Using PrimeNG DynamicDialog, I'm trying to create a consistent header-content-footer layout for all the dialogs in my use case. When opening a custom dialog component, in the dialog configuration, there's a property called templates. I could successfully create custom header and footer components by specifying header and footer properties. For content too, I would like certain common elements enforced in all custom dialogs e.g. loading indicator, loading message, border etc. I planned to do this by using NgComponentOutlet to render the custom dialog component dynamically. However, when I specify the content property, the dialog doesn't render the custom dialog component properly and throws an undefined error described further below.
DynamicDialogConfig
{
// other properties
templates: {
footer: Footer,
content: BaseContent,
},
}
BaseContent definition
@Component({
selector: 'base-content',
standalone: true,
imports: [CommonModule],
template: `
<div class="card">
<ng-container *ngComponentOutlet="projectedComponent"></ng-container>
</div> `,
})
export class BaseContent implements OnInit {
projectedComponent = null;
constructor(public ref: DynamicDialogRef) {}
async ngOnInit() {
this.projectedComponent = await firstValueFrom(
this.ref.onChildComponentLoaded
);
}
}
Undefined error
On debugging, I found that it errors out when loadChildComponent() is called. More specifically, the insertionPoint is undefined.
Minimum reproducible example:
PrimeNG DynamicDialog - content template
Is something wrong with the design ? or with the usage of content property ?
1 Answer 1
The template content replaces the component contents, hence it is blank.
Instead pass in the content component ( which contains the reusable stuff ) into the dialog service open method.
show() {
this.ref = this.dialogService.open(BaseContent, {
header: 'Product List',
width: '50vw',
modal: true,
contentStyle: { overflow: 'auto' },
breakpoints: {
'960px': '75vw',
'640px': '90vw',
},
data: {
component: ProductListDemo,
},
templates: {
footer: Footer,
// content: BaseContent,
},
});
We then pass in the component to be shown as a data property, we can render this in the content component.
import { Component, inject } from '@angular/core';
import { DynamicDialogConfig } from 'primeng/dynamicdialog';
import { CommonModule } from '@angular/common';
@Component({
selector: 'base-content',
standalone: true,
imports: [CommonModule],
template: `
<div class="card">
@if(projectedComponent) {
<ng-container *ngComponentOutlet="projectedComponent"></ng-container>
}
</div> `,
})
export class BaseContent {
projectedComponent = null;
dynamicDialogConfig = inject(DynamicDialogConfig);
ngOnInit() {
this.projectedComponent = this.dynamicDialogConfig.data.component;
}
}
Stackblitz Demo
1 Comment
Explore related questions
See similar questions with these tags.