3

I am using PrimeNg library. It has nice <p-dialog> component, which creates dialogs draggable by default. But in certain context, I am using PrimeNg's API dialogService, to create the dialog dynamically. Notice the this.dialogService.open().

But in this case, the dialog is not draggable.

Is there any workaround to make it work?

Sample code

class MyClass {
constructor(private readonly dialogService: DialogService) {}

    openDialog(options: KonsolidacniKonfliktDialogOptions): DynamicDialogRef {
        const dialogRef = this.dialogService.open(SomeComponentToRenderInsideDialog, {
            header: options.dialogHeader,
            width: this.dialogWidth,
            height: this.dialogHeight,
            styleClass: this.dialogStyleClass,
            data: {
                whatever: options.whatever,
            },
        });

        return dialogRef;
    }
}
David Votrubec
  • 3,968
  • 3
  • 33
  • 44

2 Answers2

0

In this example the dialog box is draggable :

https://stackblitz.com/edit/angular-primeng-dialog-yodw4v

Greg-A
  • 772
  • 1
  • 19
  • 41
  • 1
    Yes, but they are using the `` component, not the `dynamicDialog` invoked via API. The `` can only display already known content, not dynamic one. Or I would have to bend it and hack it, which seems like an overkill – David Votrubec Oct 25 '19 at 19:23
  • we can make prime Ng Dynamic Dialog draggable with the help of directive – KiranPurbey Aug 08 '22 at 11:08
0

Here's a directive to achieve the required drag behavior

import {AfterViewInit, Directive, ElementRef, Input, NgZone, OnDestroy} from "@angular/core";
import { Subject } from "rxjs";
import { fromEvent } from 'rxjs';
import { map, switchMap, takeUntil } from "rxjs/operators";



@Directive({
  selector: "[draggabel]"
})
export class DraggabelDirective implements AfterViewInit, OnDestroy  {


  @Input() dragHandle: string;
  @Input() dragTarget: string;

  // Element to be dragged
  private target: HTMLElement;
  // Drag handle
  private handle: HTMLElement;
  private delta = {x: 0, y: 0};
  private offset = {x: 0, y: 0};



  private destroy$ = new Subject<void>();

  constructor(private elementRef: ElementRef, private zone: NgZone) {
  }

  public ngAfterViewInit(): void {
    this.handle = this.dragHandle ? document.querySelector(this.dragHandle) as HTMLElement :
      this.elementRef.nativeElement;
    this.target = document.querySelector(this.dragTarget) as HTMLElement;
    this.setupEvents();
  }

  public ngOnDestroy(): void {
    this.destroy$.next();
  }

  private setupEvents() {
    this.zone.runOutsideAngular(() => {
      const mousedown$ = fromEvent(this.handle, "mousedown");
      const mousemove$ = fromEvent(document, "mousemove");
      const mouseup$ = fromEvent(document, "mouseup");

      const mousedrag$ = mousedown$.pipe(
        switchMap((event: MouseEvent) => {
          const startX = event.clientX;
          const startY = event.clientY;

          return mousemove$.pipe(
            map((event: MouseEvent) => {
              event.preventDefault();
              this.delta = {
                x: event.clientX - startX,
                y: event.clientY - startY
              };
            }),
            takeUntil(mouseup$)
          );
        }),
        takeUntil(this.destroy$)
      );

      mousedrag$.subscribe(() => {
        if (this.delta.x === 0 && this.delta.y === 0) {
          return;
        }

        this.translate();
      });

      mouseup$.pipe(
        takeUntil(this.destroy$)
      ).subscribe(() => {
        this.offset.x += this.delta.x;
        this.offset.y += this.delta.y;
        this.delta = {x: 0, y: 0};
      });
    });
  }

  private translate() {
    const xNewPosition = this.offset.x + this.delta.x;
    const yNewPosition = this.offset.y + this.delta.y;
    requestAnimationFrame(() => {
      this.target.style.transform = `
        translate(${xNewPosition}px,
                  ${yNewPosition}px)
      `;
    });
  }
}

Usage:

<some-dialog draggabel
             dragTarget=".p-dynamic-dialog" 
             dragHandle=".p-dynamic-dialog"
>
</some-dialog>

it's based on Oleg Varaksin Medium Blog with RxJs code and observable imports updated to use pipe()

Nader
  • 190
  • 9