Angular cdkDragDrop 行为随着 Angular 的更新而改变,拖动开始时 UI 不再更新
我们有一个包含可以拖放项目的组件,我们使用 CDK 拖/放模块来管理它。
部分功能是当用户开始拖动时更改底层对象的属性。为了更新 UI,我们调用 ChangeDetectorRef.detectChanges()。
在 Angular 版本 9 上,这工作得很好,但是自从更新到版本 12.1 后,UI 不再更新,直到拖动的项目被放下,我找不到让它工作的方法,
这是该组件的简化版本:
HTML:
<div cdkDropList>
<div cdkDrag
(cdkDragStarted)="onCdkDragStarted($event)"
*ngFor="let step of steps">Step: {{step.id}} {{step.text}}</div>
</div>
代码:
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();
}
}
使用 Angular 9,一旦开始拖动,UI 就会更新:
使用 Angular 12(或 13),代码完全相同,但 UI 不同t 更新,直到拖动的项目被删除:
有没有办法让 UI 在拖动开始后更新?
Stackblitz Angular 9:https://stackblitz.com/edit/angular-ivy-s4pmmm
StackBlitz 最新 Angular:https://stackblitz.com/edit/angular-ivy-ztdufb
的答案后显示问题
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:
With Angular 12 (or 13), the code is the exact same, but the UI doesn't update until the dragged item is dropped:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
恐怕您需要创建一个
*cdkDragPreview
。还有一个 cdkDrag 它有点?@X##??!!因为您需要考虑几件事:拖动的大小、拖动元素时的点...为了考虑所有这些,我通常创建两个变量
并且 cdkDrag 使用 (cdkDragMoved) 和 (mousedown) -您还需要使用 (cdkDragStarted) 和可能的 (cdkDragEnded) 所以你的 .html 变得像
和 .ts
请参阅 stackblitz 我如何传递“索引”到函数 (onDragStarted) 和 (onDragEnded) 来更改“对象”数组(您不需要使用像您的复杂的
$event.source.__ngContext__[8].ngForOf[$eve....
注意:您还可以检查属性 event.source 或 event.source.element 来获取 HTML 元素,您可以还将属性 cdkDragData 添加到您的 Drag
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
And the cdkDrag use (cdkDragMoved) and (mousedown) -you also need use (cdkDragStarted) and possible (cdkDragEnded) so your .html becomes like
And the .ts
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