添加新项目后的 ng2-dragula 显示在顶部
ng2-dragula after adding new item it's getting displayed at the top
我正在使用 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 always returns ViewContainer host(Comment node)ref 如果我们在末尾添加item:
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 returns 最后渲染节点(最后 <li/>
元素)ref
function renderAttachEmbeddedView(
elementData: ElementData, prevView: ViewData|null, view: ViewData) {
const prevRenderNode =
prevView ? renderNode(prevView, prevView.def.lastRenderRootNode!) : elementData.renderElement;
...
}
解决方案可能是将拖动的元素恢复到原始容器,这样我们就可以让 built-in ngForOf
Angular 指令进行智能差异化。
顺便说一句,Angular material DragDropModule
中使用了相同的技术。它会记住拖动元素的位置,并在我们放下项目后将其插入到 DOM 中的旧位置,这很重要。
我正在使用 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 always returns ViewContainer host(Comment node)ref 如果我们在末尾添加item:
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 returns 最后渲染节点(最后 <li/>
元素)ref
function renderAttachEmbeddedView(
elementData: ElementData, prevView: ViewData|null, view: ViewData) {
const prevRenderNode =
prevView ? renderNode(prevView, prevView.def.lastRenderRootNode!) : elementData.renderElement;
...
}
解决方案可能是将拖动的元素恢复到原始容器,这样我们就可以让 built-in ngForOf
Angular 指令进行智能差异化。
顺便说一句,Angular material DragDropModule
中使用了相同的技术。它会记住拖动元素的位置,并在我们放下项目后将其插入到 DOM 中的旧位置,这很重要。