问题描述
我正在使用ng2-dragula进行拖放功能。我在将第一个元素(或任何元素)拖放到末尾,然后尝试使用addNewItem按钮将新项目添加到数组时看到问题,新项目没有被添加到末尾。如果我不将元素放到末尾,则会在UI的末尾添加新项。 在任何情况下,我都希望新项目显示在底部。任何帮助表示赞赏。 Angular 7无法重现此问题。我看到Angular 9会发生这种情况。
JS
export class SampleComponent {
items = ['Candlestick','Dagger','Revolver','Rope','Pipe','Wrench'];
constructor(private dragulaService: DragulaService) {
dragulaService.createGroup("bag-items",{
removeOnSpill: false
});
}
public addNewItem() {
this.items.push('New Item');
}
}
HTML
<div class="container" [dragula]='"bag-items"' [(dragulaModel)]='items'>
<div *ngFor="let item of items">{{ item }}</div>
</div>
我编辑了注释中的stackblitz,以帮助可视化问题。将单位拖到列表底部时,似乎会触发此事件。更新的stackblitz:https://stackblitz.com/edit/ng2-dragula-base-ykm8fz?file=src/app/app.component.html ItemsAddedOutOfOrder
解决方法
您可以尝试恢复掉落的旧物品的位置。
constructor(private dragulaService: DragulaService) {
this.subscription = this.dragulaService.drop().subscribe(({ name }) => {
this.dragulaService.find(name).drake.cancel(true);
});
}
说明
Ivy和ViewEngine在特定索引处插入ViewRef的方式有所不同。他们在不同的beforeNode上中继
如果我们将项目添加到末尾,Ivy总是返回ViewContainer主机(注释节点)ref :
export function getBeforeNodeForView(viewIndexInContainer: number,lContainer: LContainer): RNode|
null {
const nextViewIndex = CONTAINER_HEADER_OFFSET + viewIndexInContainer + 1;
if (nextViewIndex < lContainer.length) {
const lView = lContainer[nextViewIndex] as LView;
const firstTNodeOfView = lView[TVIEW].firstChild;
if (firstTNodeOfView !== null) {
return getFirstNativeNode(lView,firstTNodeOfView);
}
}
return lContainer[NATIVE]; <============================= this one
}
ViewEngine返回最后渲染的节点(最后一个<li/>
元素)ref
function renderAttachEmbeddedView(
elementData: ElementData,prevView: ViewData|null,view: ViewData) {
const prevRenderNode =
prevView ? renderNode(prevView,prevView.def.lastRenderRootNode!) : elementData.renderElement;
...
}
解决方案可能是将拖动的元素还原回原始容器,以便我们可以让内置ngForOf
Angular指令进行智能区分。
顺便说一句,在Angular材质DragDropModule
中使用了相同的技术。它会记住拖动元素的位置,并在拖放项目后将其插入到DOM中重要的旧位置。