From 3f67d61c7c13b6e2a79e0a9f88338a90b2cb04f1 Mon Sep 17 00:00:00 2001 From: "BEAST\\rohan" Date: Tue, 9 Jun 2026 21:52:35 +0530 Subject: [PATCH] ## Summary - Add `onDragStart` output to `p-dialog` and emit it from `initDrag()` - Bridge `(onDragStart)` in `DynamicDialog` to `DynamicDialogRef.dragStart()` - Add unit tests for both components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #19611 ## Problem `DynamicDialogRef.onDragStart` never emitted in v21 because drag handling moved into `p-dialog`, but only `onDragEnd` was wired through to the ref. ## Test plan - [x] `dialog.spec.ts` — `onDragStart` emission from `initDrag()` - [x] `dynamicdialog.spec.ts` — `onDialogDragStart` forwards to ref - [x] Manual repro: open `DialogService` dialog, drag header, confirm `onDragStart` and `onDragEnd` both fire --- packages/primeng/src/dialog/dialog.spec.ts | 44 +++++++++++++++++++ packages/primeng/src/dialog/dialog.ts | 7 +++ .../src/dynamicdialog/dynamicdialog.spec.ts | 11 +++++ .../src/dynamicdialog/dynamicdialog.ts | 6 +++ 4 files changed, 68 insertions(+) diff --git a/packages/primeng/src/dialog/dialog.spec.ts b/packages/primeng/src/dialog/dialog.spec.ts index 0dbefb31c29..a9de2719936 100644 --- a/packages/primeng/src/dialog/dialog.spec.ts +++ b/packages/primeng/src/dialog/dialog.spec.ts @@ -49,6 +49,7 @@ import { Dialog } from './dialog'; (onMaximize)="onMaximizeEvent($event)" (onResizeInit)="onResizeInitEvent($event)" (onResizeEnd)="onResizeEndEvent($event)" + (onDragStart)="onDragStartEvent($event)" (onDragEnd)="onDragEndEvent($event)" (visibleChange)="onVisibleChangeEvent($event)" > @@ -99,6 +100,7 @@ class TestBasicDialogComponent { maximizeEvent: any = null as any; resizeInitEvent: any = null as any; resizeEndEvent: any = null as any; + dragStartEvent: any = null as any; dragEndEvent: any = null as any; visibleChangeEvent: any = null as any; @@ -126,6 +128,10 @@ class TestBasicDialogComponent { this.resizeEndEvent = event; } + onDragStartEvent(event: any) { + this.dragStartEvent = event; + } + onDragEndEvent(event: any) { this.dragEndEvent = event; } @@ -519,6 +525,20 @@ describe('Dialog', () => { expect(component.onResizeInitEvent).toHaveBeenCalledWith(mouseEvent); }); + it('should emit onDragStart event when dragging starts', async () => { + spyOn(component, 'onDragStartEvent'); + + component.visible = true; + fixture.changeDetectorRef.markForCheck(); + await fixture.whenStable(); + await new Promise((resolve) => setTimeout(resolve, 0)); + + const mouseEvent = new MouseEvent('mousedown'); + dialogInstance.onDragStart.emit(mouseEvent); + + expect(component.onDragStartEvent).toHaveBeenCalledWith(mouseEvent); + }); + it('should emit onDragEnd event when dragging ends', async () => { spyOn(component, 'onDragEndEvent'); @@ -1300,6 +1320,30 @@ describe('Dialog', () => { expect(component.onResizeInitEvent).toHaveBeenCalledWith(mouseEvent); }); + it('should emit onDragStart event from initDrag', async () => { + component.draggable = true; + fixture.changeDetectorRef.markForCheck(); + await fixture.whenStable(); + + component.visible = true; + fixture.changeDetectorRef.markForCheck(); + await fixture.whenStable(); + await new Promise((resolve) => setTimeout(resolve, 0)); + + spyOn(dialogInstance.onDragStart, 'emit'); + + const targetElement = document.createElement('div'); + const mouseEvent = new MouseEvent('mousedown', { clientX: 100, clientY: 100 }); + Object.defineProperty(mouseEvent, 'target', { value: targetElement }); + Object.defineProperty(mouseEvent, 'pageX', { value: 100 }); + Object.defineProperty(mouseEvent, 'pageY', { value: 100 }); + + dialogInstance.initDrag(mouseEvent); + + expect(dialogInstance.dragging).toBe(true); + expect(dialogInstance.onDragStart.emit).toHaveBeenCalledWith(mouseEvent); + }); + it('should emit onDragEnd event', () => { const dragEvent = new DragEvent('dragend'); spyOn(component, 'onDragEndEvent'); diff --git a/packages/primeng/src/dialog/dialog.ts b/packages/primeng/src/dialog/dialog.ts index c18af24cd59..5d45a835788 100755 --- a/packages/primeng/src/dialog/dialog.ts +++ b/packages/primeng/src/dialog/dialog.ts @@ -447,6 +447,12 @@ export class Dialog extends BaseComponent implements OnInit, * @group Emits */ @Output() onResizeEnd: EventEmitter = new EventEmitter(); + /** + * Callback to invoke when dialog dragging is initiated. + * @param {MouseEvent} event - Mouse event. + * @group Emits + */ + @Output() onDragStart: EventEmitter = new EventEmitter(); /** * Callback to invoke when dialog dragging is completed. * @param {DragEvent} event - Drag event. @@ -851,6 +857,7 @@ export class Dialog extends BaseComponent implements OnInit, (this.container() as HTMLDivElement).style.margin = '0'; this.document.body.setAttribute('data-p-unselectable-text', 'true'); !this.$unstyled() && addStyle(this.document.body, { 'user-select': 'none' }); + this.onDragStart.emit(event); } } diff --git a/packages/primeng/src/dynamicdialog/dynamicdialog.spec.ts b/packages/primeng/src/dynamicdialog/dynamicdialog.spec.ts index f46c15c8511..dafe9d7bf64 100644 --- a/packages/primeng/src/dynamicdialog/dynamicdialog.spec.ts +++ b/packages/primeng/src/dynamicdialog/dynamicdialog.spec.ts @@ -327,6 +327,17 @@ describe('DynamicDialog', () => { expect(mockDialogRef.dragStart).toHaveBeenCalledWith(mouseEvent); }); + it('should forward drag start from dialog to dialog ref', () => { + const mouseEvent = new MouseEvent('mousedown'); + Object.defineProperty(mouseEvent, 'pageX', { value: 100 }); + Object.defineProperty(mouseEvent, 'pageY', { value: 100 }); + + component.onDialogDragStart(mouseEvent); + + expect(component.dragging).toBe(true); + expect(mockDialogRef.dragStart).toHaveBeenCalledWith(mouseEvent); + }); + it('should not initialize drag when clicking on header icons', () => { const iconElement = document.createElement('i'); iconElement.className = 'p-dialog-header-icon'; diff --git a/packages/primeng/src/dynamicdialog/dynamicdialog.ts b/packages/primeng/src/dynamicdialog/dynamicdialog.ts index 7269663cb5f..a474bc3d93c 100755 --- a/packages/primeng/src/dynamicdialog/dynamicdialog.ts +++ b/packages/primeng/src/dynamicdialog/dynamicdialog.ts @@ -54,6 +54,7 @@ const DYNAMIC_DIALOG_INSTANCE = new InjectionToken('DYNAMIC_DIALO (onResizeInit)="onDialogResizeInit($event)" (onResizeEnd)="onDialogResizeEnd($event)" (onDragEnd)="onDialogDragEnd($event)" + (onDragStart)="onDialogDragStart($event)" (visibleChange)="onVisibleChange($event)" [pt]="ddconfig.pt" appendTo="self" @@ -306,6 +307,11 @@ export class DynamicDialog extends BaseComponent { this.dialogRef.dragEnd(event); } + onDialogDragStart(event: MouseEvent) { + this.dragging = true; + this.dialogRef.dragStart(event); + } + close() { this.visible = false; this.cd.markForCheck();