我有一个基于这个 stackblitz 的组件:https ://stackblitz.com/edit/angular-5mf7hl
当我尝试交换列表中的元素时出现问题。我希望数组项交换位置。在上面的 stackblitz 示例中,当目标 listItem 被 sourceItem 替换时,它会在列表中的预览期间被向前或向后推送。通过在这个 StackOverflow 问题中从 Shinjo 借用一些代码,我设法让它们交换位置:Angular 7 drag Drop swapping elements
交换本身很完美,但是,当我将一个列表项拖到另一个列表项上时,预览不正确。当您释放时,它会自行更正,并且 listItem 会出现在数组中的正确位置。我想要的是,在放开拖动的项目之前,源列表项和目标列表项在预览期间交换位置。您可以查看上面的 stackblitz 以直观地看到问题。
应用组件.ts
import { Component, NgModule, ViewChild } from '@angular/core';
import {
CdkDrag,
CdkDragStart,
CdkDropList, CdkDropListContainer, CdkDropListGroup,
moveItemInArray
} from "@angular/cdk/drag-drop";
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
@ViewChild(CdkDropListGroup) listGroup: CdkDropListGroup<CdkDropList>;
@ViewChild(CdkDropList) placeholder: CdkDropList;
public items: Array<number> = [1, 2, 3, 4, 5, 6, 7, 8, 9];
public target: CdkDropList;
public targetIndex: number;
public source: CdkDropListContainer;
public sourceIndex: number;
constructor() {
this.target = null;
this.source = null;
}
ngAfterViewInit() {
let phElement = this.placeholder.element.nativeElement;
phElement.style.display = 'none';
phElement.parentNode.removeChild(phElement);
}
drop() {
if (!this.target)
return;
let phElement = this.placeholder.element.nativeElement;
let parent = phElement.parentNode;
phElement.style.display = 'none';
parent.removeChild(phElement);
parent.appendChild(phElement);
parent.insertBefore(this.source.element.nativeElement,
parent.children[this.sourceIndex]);
this.target = null;
this.source = null;
if (this.sourceIndex != this.targetIndex) {
let oldtarget = this.items[this.sourceIndex];
this.items[this.sourceIndex] = this.items[this.targetIndex];
this.items[this.targetIndex] = oldtarget;
}
}
enter = (drag: CdkDrag, drop: CdkDropList) => {
if (drop == this.placeholder)
return true;
let phElement = this.placeholder.element.nativeElement;
let dropElement = drop.element.nativeElement;
let dragIndex = __indexOf(dropElement.parentNode.children,
drag.dropContainer.element.nativeElement);
let dropIndex = __indexOf(dropElement.parentNode.children, dropElement);
if (!this.source) {
this.sourceIndex = dragIndex;
this.source = drag.dropContainer;
let sourceElement = this.source.element.nativeElement;
phElement.style.width = sourceElement.clientWidth + 'px';
phElement.style.height = sourceElement.clientHeight + 'px';
sourceElement.parentNode.removeChild(sourceElement);
}
this.targetIndex = dropIndex;
this.target = drop;
phElement.style.display = '';
dropElement.parentNode.insertBefore(phElement, (dragIndex < dropIndex)
? dropElement.nextSibling : dropElement);
this.source.start();
this.placeholder.enter(drag, drag.element.nativeElement.offsetLeft,
drag.element.nativeElement.offsetTop);
return false;
}
}
function __indexOf(collection, node) {
return Array.prototype.indexOf.call(collection, node);
};
App.component.html
<div class="example-container" cdkDropListGroup>
<div cdkDropList [cdkDropListEnterPredicate]="enter" (cdkDropListDropped)="drop()" #placeholder></div>
<div cdkDropList *ngFor="let item of items"
[cdkDropListEnterPredicate]="enter" (cdkDropListDropped)="drop()">
<div cdkDrag class="example-box">{{item}}</div>
</div>
</div>
App.component.css
.example-list {
list-style-type: none;
padding: 0;
}
.example-list li {
display: table-cell;
padding: 4px;
}
.example-container {
display: flex;
flex-wrap: wrap;
min-width: 600px;
max-width: 900px;
}
.example-box {
width: 200px;
height: 200px;
border: solid 1px #ccc;
font-size: 30pt;
font-weight: bold;
color: rgba(0, 0, 0, 0.87);
cursor: move;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
background: #fff;
border-radius: 4px;
position: relative;
z-index: 1;
transition: box-shadow 200ms cubic-bezier(0, 0, 0.2, 1);
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2),
0 2px 2px 0 rgba(0, 0, 0, 0.14),
0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.example-box:active {
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14),
0 3px 14px 2px rgba(0, 0, 0, 0.12);
opacity: .6;
}
.cdk-drop-list {
display: flex;
padding-right: 10px;
padding-bottom: 10px;
}
.cdk-drag-preview {
box-sizing: border-box;
border-radius: 4px;
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14),
0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.cdk-drag-placeholder {
opacity: .3;
}
.cdk-drag-animating {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}