#19473·primeng

DynamicDialog Custom Template causes Repaint of dialog

Author: bernhardsmartpointCreated Mar 11, 2026Updated Sep 8, 2026
LabelsType: BugResolution: Stale

Describe the bug

DynamicDialog executes an unintentional repaint when using custom content template

Reproducer

StackBlitz Bug Demonstration

Actual

When using a custom content template, the enter animation fires a second time and any of the described scenarios. This repaint leads to a strange flickering behavior of the dialog. Reproduced by observing p-overlay-mask-enter-active appearing twice/multiple times on the mask element.

The repaint can be triggered by three scenarios:

  1. Without any interaction - The repaint occurs automatically shortly after the dialog opens, without any mouse interaction
  2. Clicking inside the dialog - If the repaint hasn't occurred yet, clicking anywhere inside the dialog content triggers it
  3. Clicking the close button - If the repaint hasn't occurred yet, clicking the X close button triggers it

Note: This bug does not occur when using the default content template (without the templates option).

Possible root cause (observation)

Based on analyzing the code, there appears to be a problematic flow that might be causing a renderMask false→true cycle:

Observation 1: Dialog.close() sets visible directly (dialog.ts):

typescript
// current implementation
close(event: Event) {
    this.visible = false;              // sets internal state
    this.visibleChange.emit(this.visible); // also notifies parent
    event.preventDefault();
}

Observation 2: DynamicDialog.onVisibleChange() never sets this.visible = false (dynamicdialog.ts):

typescript
// current implementation
onVisibleChange(visible: boolean) {
    if (!visible) {
        this.dialogRef.close(); // never sets this.visible = false
    }
}

Potential problematic flow:

close() called
  → visibleChange(false) → DynamicDialog.onVisibleChange()
      → dialogRef.close() → DynamicDialog.close() → cd.markForCheck()
          → onAfterLeave(): renderMask.set(false), onHide.emit()
              → onDialogHide() → dialogRef.destroy() → cd.markForCheck()
                  → CD re-evaluates [(visible)]="visible"
                      → DynamicDialog.visible might still be true  ← never set to false
                          → Dialog.visible setter: _visible=true, maskVisible=false
                              → renderMask.set(true)   ← false→true re-trigger?
                              → pMotion might fire enter animation again

Pull Request Link

No response

Reason for not contributing a PR

  • Lack of time
  • Unsure how to implement the fix/feature
  • Difficulty understanding the codebase
  • Other

Other Reason

I will add a Pull Request as soon as I found the exact issue in the primeng implementation of the dynamic dialog with custom templates.

Reproducer

https://stackblitz.com/edit/github-fpcqwxcz

Environment

PrimeNG version: 21.x
Angular version: 21.x

No deviations from the default primeng project template setup except the custom template usage of the dynamic dialog. See Stackblitz demonstration.

Angular version

21.2.1

PrimeNG version

v21

Node version

24.14.0

Browser(s)

Chrome v145.0.7632.160

Steps to reproduce the behavior

  1. Open a DynamicDialog via DialogService.open() with a custom content template (using the templates.content option).
  2. Observe the behavior in one of three scenarios:
    • Wait without any mouse interaction after the dialog opens
    • Click anywhere inside the dialog content
    • Click the X close button

Expected behavior

Enter animation fires once (on open). No repaint or re-triggering of the animation should occur. Dialog does not get closed and reopened unintentionally.