Angular 拖放绝对位置元素选择了错误的索引
Angular Drag and Drop absolute position elements selecting wrong index
我正在尝试将项目拖到两个列表中。底部列表是典型的排序列表(如 "inventory"),但我希望顶部项目未排序且可放置在任何地方(如 "game board")。
我大部分时间都在使用它,但是当放入顶部框时 event.currentIndex 始终为 0。但是当从那里拖出时,我得到不同的 event.previousIndex 值,这意味着模型和 DOM 元素并不总是匹配。
这里 stackblitz 表达了我的意思。将一些项目拖到顶部框中并进行操作,您会发现有时会移动错误的项目。
当您以相反的顺序进行交互时最值得注意,例如:
- 将项目 "One"、"Two"、"Three" 拖到顶部框中(按此顺序)
- 尝试将物品 "Three"、"Two"、"One" 放回底盒(按此顺序)
cdkDropListSortingDisabled
选项仅在同一容器内移动项目时有效。如果您从一个容器移动到另一个容器,则 Angular sorts 方块位置:
this._itemPositions = this._activeDraggables.map(drag => {
const elementToMeasure = drag.getVisibleElement();
return {drag, offset: 0, clientRect: getMutableClientRect(elementToMeasure)};
}).sort((a, b) => {
return isHorizontal ? a.clientRect.left - b.clientRect.left :
a.clientRect.top - b.clientRect.top;
});
由于您没有提供方向并且默认是垂直的,因此它按 top
位置排序。
顶部框 event.currentIndex
始终为 0,因为您使用绝对定位并且占位符始终位于顶部。
尝试添加以下样式以查看占位符的显示位置:
.cdk-drag-placeholder {
opacity: 1;
background: red;
}
要修复它,您可以自己计算 currentIndex
,例如像这样:
const isWithinSameContainer = event.previousContainer === event.container;
let toIndex = event.currentIndex;
if (event.container.sortingDisabled) {
const arr = event.container.data.sort((a, b) => a.top - b.top);
const targetIndex = arr.findIndex(item => item.top > top);
toIndex =
targetIndex === -1
? isWithinSameContainer
? arr.length - 1
: arr.length
: targetIndex;
}
const item = event.previousContainer.data[event.previousIndex];
item.top = top;
item.left = left;
if (isWithinSameContainer) {
moveItemInArray(event.container.data, event.previousIndex, toIndex);
} else {
transferArrayItem(
event.previousContainer.data,
event.container.data,
event.previousIndex,
toIndex
);
}
我正在尝试将项目拖到两个列表中。底部列表是典型的排序列表(如 "inventory"),但我希望顶部项目未排序且可放置在任何地方(如 "game board")。
我大部分时间都在使用它,但是当放入顶部框时 event.currentIndex 始终为 0。但是当从那里拖出时,我得到不同的 event.previousIndex 值,这意味着模型和 DOM 元素并不总是匹配。
这里 stackblitz 表达了我的意思。将一些项目拖到顶部框中并进行操作,您会发现有时会移动错误的项目。
当您以相反的顺序进行交互时最值得注意,例如:
- 将项目 "One"、"Two"、"Three" 拖到顶部框中(按此顺序)
- 尝试将物品 "Three"、"Two"、"One" 放回底盒(按此顺序)
cdkDropListSortingDisabled
选项仅在同一容器内移动项目时有效。如果您从一个容器移动到另一个容器,则 Angular sorts 方块位置:
this._itemPositions = this._activeDraggables.map(drag => {
const elementToMeasure = drag.getVisibleElement();
return {drag, offset: 0, clientRect: getMutableClientRect(elementToMeasure)};
}).sort((a, b) => {
return isHorizontal ? a.clientRect.left - b.clientRect.left :
a.clientRect.top - b.clientRect.top;
});
由于您没有提供方向并且默认是垂直的,因此它按 top
位置排序。
顶部框 event.currentIndex
始终为 0,因为您使用绝对定位并且占位符始终位于顶部。
尝试添加以下样式以查看占位符的显示位置:
.cdk-drag-placeholder {
opacity: 1;
background: red;
}
要修复它,您可以自己计算 currentIndex
,例如像这样:
const isWithinSameContainer = event.previousContainer === event.container;
let toIndex = event.currentIndex;
if (event.container.sortingDisabled) {
const arr = event.container.data.sort((a, b) => a.top - b.top);
const targetIndex = arr.findIndex(item => item.top > top);
toIndex =
targetIndex === -1
? isWithinSameContainer
? arr.length - 1
: arr.length
: targetIndex;
}
const item = event.previousContainer.data[event.previousIndex];
item.top = top;
item.left = left;
if (isWithinSameContainer) {
moveItemInArray(event.container.data, event.previousIndex, toIndex);
} else {
transferArrayItem(
event.previousContainer.data,
event.container.data,
event.previousIndex,
toIndex
);
}