Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

194
Vistas
Angular cdkDragDrop behavior changed with update of Angular, UI no longer updates when dragging starts

We have a component which has items that can be dragged and dropped, we use the CDK drag/drop module for managing this.

Part of the functionality is to change a property of the underlying object when the user starts dragging. To get the UI to update we call ChangeDetectorRef.detectChanges().

When on version 9 of Angular this worked fine, however since updating to version 12.1 the UI no longer updates until the dragged item is dropped and I cannot find a way to get it working

Here is a simplified version of the component:

HTML:

<div cdkDropList>
<div cdkDrag 
 (cdkDragStarted)="onCdkDragStarted($event)"
 *ngFor="let step of steps">Step: {{step.id}}  {{step.text}}</div>
</div>

Code:

import { ChangeDetectorRef, Component} from '@angular/core';

@Component({
  selector: 'drag-poc',
  templateUrl: 'drag-poc.component.html',
  styles: []
})
export class DragPocComponent { 
  steps: any[] = [
    { id: 1, text: '' },
    { id: 2, text: '' },
    { id: 3, text: '' },
    { id: 4, text: '' },
    { id: 5, text: '' },
  ];

  constructor(private ref: ChangeDetectorRef){

  }

  onCdkDragStarted($event){
    // this is just a hack to get a reference to the array object that is being dragged
    const draggedItem = $event.source.__ngContext__[8].ngForOf[$event.source.__ngContext__[8].index];

    draggedItem.text = "MOVED";
    this.ref.detectChanges();
  }
}

With Angular 9 the UI updates once the dragging starts:

Dragging with updated UI

With Angular 12 (or 13), the code is the exact same, but the UI doesn't update until the dragged item is dropped:

Dragging with non-updated UI

Is there a way to get the UI to update once the dragging starts?

Stackblitz Angular 9: https://stackblitz.com/edit/angular-ivy-s4pmmm

StackBlitz Latest Angular: https://stackblitz.com/edit/angular-ivy-ztdufb

EDIT: the Latest Angular StackBlitz is updated to show the problem after the answer from @Eliseo

updated problem

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

I'm afraid that you need create a *cdkDragPreview. And a cdkDrag it's a bit ?@X##??!! because you need take acount several thing: the size of the drag, the point when you drag the element...

To take account all of this I usually create two variables

  style: any = null;
  offset:any=null

And the cdkDrag use (cdkDragMoved) and (mousedown) -you also need use (cdkDragStarted) and possible (cdkDragEnded) so your .html becomes like

<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
    <div class="example-box" *ngFor="let movie of movies;let i=index" cdkDrag 
    [cdkDragData]="movie"
    (cdkDragStarted)="onDragStarted($event,i)"
    (cdkDragMoved)="onDragMove($event)"
    (cdkDragEnded)="onDragEnded($event,i)"
    
     (mousedown)="setStyle($event)" >{{movie.title}}{{movie.text}}
      <div  *cdkDragPreview class="example-box" [ngStyle]="style">
        {{movie.title}}{{movie.text}}
      </div>
    </div>
  </div>

And the .ts

  drop(event: CdkDragDrop<any[]>) {
    moveItemInArray(this.movies, event.previousIndex, event.currentIndex);
  }
  onDragStarted(event:CdkDragStart<any>,index:number)
  {
      //you can use
      this.movies[index].text="moved"
      //or use
      event.source.data.text="moving...."

  }
  onDragEnded(event:CdkDragEnd<any>,index:number)
  {
    this.movies[index].text=""
  }
  setStyle(event: MouseEvent) {
    const rect = (event.target as HTMLElement).getBoundingClientRect();
    this.style = { width: rect.width + 'px', height: rect.height + 'px'}
    this.offset={x:event.offsetX,y:event.offsetY };
  }
  public onDragMove(event: CdkDragMove<any>): void {
    const el=(document.getElementsByClassName('cdk-drag-preview')[0])as any
    const xPos = event.pointerPosition.x - this.offset.x;
    const yPos = event.pointerPosition.y - this.offset.y;
    el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`;
  }

See in the stackblitz how I pass the "index" to the functions (onDragStarted) and (onDragEnded) to change the array of "object" (you needn't use some complex like your $event.source.__ngContext__[8].ngForOf[$eve....

NOTE: You can also check the property event.source or event.source.element to get the HTML element, you can also add a property cdkDragData to your Drag

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda