Tenemos un componente que tiene elementos que se pueden arrastrar y soltar, usamos el módulo de arrastrar/soltar de CDK para administrar esto.
Parte de la funcionalidad es cambiar una propiedad del objeto subyacente cuando el usuario comienza a arrastrar. Para actualizar la interfaz de usuario, llamamos a ChangeDetectorRef.detectChanges().
Cuando estaba en la versión 9 de Angular, esto funcionó bien, sin embargo, desde que se actualizó a la versión 12.1, la interfaz de usuario ya no se actualiza hasta que se suelta el elemento arrastrado y no puedo encontrar una manera de hacerlo funcionar.
Aquí hay una versión simplificada del componente:
HTML:
<div cdkDropList> <div cdkDrag (cdkDragStarted)="onCdkDragStarted($event)" *ngFor="let step of steps">Step: {{step.id}} {{step.text}}</div> </div>Código:
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(); } }Con Angular 9, la interfaz de usuario se actualiza una vez que comienza el arrastre:
Con Angular 12 (o 13), el código es exactamente el mismo, pero la interfaz de usuario no se actualiza hasta que se suelta el elemento arrastrado:
¿Hay alguna manera de actualizar la interfaz de usuario una vez que comience el arrastre?
Stackblitz Angular 9: https://stackblitz.com/edit/angular-ivy-s4pmmm
StackBlitz último angular: https://stackblitz.com/edit/angular-ivy-ztdufb
EDITAR: el último Angular StackBlitz se actualiza para mostrar el problema después de la respuesta de @Eliseo
Me temo que necesita crear un *cdkDragPreview . Y un cdkDrag es un poco ?@X##??!! porque debes tener en cuenta varias cosas: el tamaño del arrastre, el punto en el que arrastras el elemento...
Para tener en cuenta todo esto suelo crear dos variables
style: any = null; offset:any=nullY el uso de cdkDrag (cdkDragMoved) y (mousedown) -también necesita usar (cdkDragStarted) y posible (cdkDragEnded) para que su .html se vuelva como
<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>y los .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)`; } Vea en el stackblitz cómo paso el "índice" a las funciones (onDragStarted) y (onDragEnded) para cambiar la matriz de "objeto" (no necesita usar algún complejo como $event.source.__ngContext__[8].ngForOf[$eve....
NOTA: También puede verificar la propiedad event.source o event.source.element para obtener el elemento HTML, también puede agregar una propiedad cdkDragData a su Drag