Will Shaver
Will Shaver

Reputation: 13099

Angular cdkDragPreview not updating with data during drag

Angular 9+ (example is Angular 13) Standard cdkDropList cdkDrag item set, this example is copied directly off of the google angular examples stackblitz. I want my preview card to update when the data updates while the user is dragging. In this example, I'm doing assigning a random number every 500ms and rendering that. Note that during updates the drag preview is static.

// html
<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
  <div class="example-box" *ngFor="let movie of movies" cdkDrag>
    {{movie.title}} {{movie.number}}
  </div>
</div>

// added to drag and drop preview example
  ngOnInit(): void {
    for (let movie of this.movies) {
      setInterval(() => {
        movie.number = Math.random();
      }, 500);
    }
  }

https://stackblitz.com/edit/angular-eysbdw-pgagm5?file=src/app/cdk-drag-drop-custom-preview-example.html

Example of not updating

Upvotes: 0

Views: 1100

Answers (1)

Will Shaver
Will Shaver

Reputation: 13099

I ended up manually updating the HTML of the preview item. Here's how:

  1. Add an html element that you plan to update to the thing being dragged. In my case that was a time-indicator as I dragged the element to different locations on the page. <div class="time-indicator start-time"></div>

  2. Add methods for drop list enter and exit. I had separate drop lists with different times that I wanted to show on the dragging element.

(cdkDropListEntered)="appointmentDragEnter($event, timeBlock)" (cdkDropListExited)="appointmentDragExit($event)"

  1. Inside your drag enter/exit, update the placeholder HTML
  appointmentDragEnter(event: CdkDragEnter, timeBlock: Date): void {
    // placeholder elements aren't bound to the original component, and therefore do not get updates while dragging
    // so we manually update the html

    // tslint:disable-next-line: no-string-literal
    const preview = event.item._dragRef['_preview'] as HTMLElement;
    const startTimeElement = preview.querySelector('.start-time');
    if (startTimeElement) {
      startTimeElement.innerHTML = moment(timeBlock).format('h:mm A');
    }
  }

  appointmentDragExit(event: CdkDragExit): void {
    // tslint:disable-next-line: no-string-literal
    const preview = event.item._dragRef['_preview'] as HTMLElement;
    const startTimeElement = preview.querySelector('.start-time');
    if (startTimeElement) {
      startTimeElement.innerHTML = '';
    }
  }

Upvotes: 1

Related Questions