Angular Cdk 拖拽,等长列表
Angular Cdk Drag and drop, constant length lists
我已经为这个问题绞尽脑汁好一段时间了。我想要实现的是让两个连接的拖放列表具有恒定长度。这意味着如果我将一个元素从一个列表移动到另一个列表,一个项目就会被推到另一个列表。在 cdkDropListDropped
事件期间实现这当然是微不足道的,但我希望它在项目被拖到列表上时立即发生。
我的大部分尝试都涉及使用 cdkDropListEntered
事件来:
- 尝试简单地移动数据数组中的项目:
public enter(list: number, event: CdkDragEnter<User[]>) {
if (list === 0) {
let data = this.schedule.responsible.pop();
this.schedule.queue.unshift(data);
} else {
let data = this.schedule.queue.shift();
this.schedule.responsible.push(data);
}
}
这导致了以下类型的错误:
core.js:6185 ERROR DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node
尝试使用 CdkDropList
addItem()
、removeItem()
、getSortedItems()
。这会导致类似的问题。
尝试使用 Renderer2 移动 DOM-元素本身(并保持数据不变)
有什么方法可以达到我想要的效果吗?
This 宏伟的绘画有助于解释我想要实现的目标。
好的,我在尝试了两种解决方案后想通了。第一个涉及将占位符框添加到两个列表中,只有在它们有内容时才可见。它们的内容将是推入该列表的框的内容。同时,原始框被赋予 display: none
样式。这主要实现了我想要的行为,但由于可拖动对象的内部模型与 DOM.
之间的不匹配,存在一些视觉问题
最终奏效的是首先放弃了拥有两个列表的概念。然后排序自然解决了。但是,样式必须稍微不同,因为每个可拖动对象都需要是列表的直接后代。
附上代码和 Stackblitz 工作示例:
app.component.ts
import { Component, OnInit} from '@angular/core';
import {CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
public lists: {list1: string[], list2: string[]};
public fullList: string[];
public numList1: number;
constructor() {}
ngOnInit() {
this.lists = {
list1: ['one', 'two'],
list2: ['three', 'four']
};
this.fullList = this.lists.list1.concat(this.lists.list2);
this.numList1 = this.lists.list1.length;
}
public drop(event: CdkDragDrop<string[]>) {
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
}
}
app.component.html
<div class="list-container">
<div cdkDropList
[cdkDropListAutoScrollDisabled]="true"
[cdkDropListData]="fullList"
cdkDropListLockAxis="y"
(cdkDropListDropped)="drop($event)">
<ng-container *ngFor="let item of fullList; let index = index;">
<h2 *ngIf="index === 0">List 1</h2>
<h2 *ngIf="index === numList1">List 2</h2>
<div cdkDrag class="drop-box">{{item}}</div>
</ng-container>
</div>
</div>
我已经为这个问题绞尽脑汁好一段时间了。我想要实现的是让两个连接的拖放列表具有恒定长度。这意味着如果我将一个元素从一个列表移动到另一个列表,一个项目就会被推到另一个列表。在 cdkDropListDropped
事件期间实现这当然是微不足道的,但我希望它在项目被拖到列表上时立即发生。
我的大部分尝试都涉及使用 cdkDropListEntered
事件来:
- 尝试简单地移动数据数组中的项目:
public enter(list: number, event: CdkDragEnter<User[]>) {
if (list === 0) {
let data = this.schedule.responsible.pop();
this.schedule.queue.unshift(data);
} else {
let data = this.schedule.queue.shift();
this.schedule.responsible.push(data);
}
}
这导致了以下类型的错误:
core.js:6185 ERROR DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node
尝试使用
CdkDropList
addItem()
、removeItem()
、getSortedItems()
。这会导致类似的问题。尝试使用 Renderer2 移动 DOM-元素本身(并保持数据不变)
有什么方法可以达到我想要的效果吗?
This 宏伟的绘画有助于解释我想要实现的目标。
好的,我在尝试了两种解决方案后想通了。第一个涉及将占位符框添加到两个列表中,只有在它们有内容时才可见。它们的内容将是推入该列表的框的内容。同时,原始框被赋予 display: none
样式。这主要实现了我想要的行为,但由于可拖动对象的内部模型与 DOM.
最终奏效的是首先放弃了拥有两个列表的概念。然后排序自然解决了。但是,样式必须稍微不同,因为每个可拖动对象都需要是列表的直接后代。
附上代码和 Stackblitz 工作示例:
app.component.ts
import { Component, OnInit} from '@angular/core';
import {CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
public lists: {list1: string[], list2: string[]};
public fullList: string[];
public numList1: number;
constructor() {}
ngOnInit() {
this.lists = {
list1: ['one', 'two'],
list2: ['three', 'four']
};
this.fullList = this.lists.list1.concat(this.lists.list2);
this.numList1 = this.lists.list1.length;
}
public drop(event: CdkDragDrop<string[]>) {
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
}
}
app.component.html
<div class="list-container">
<div cdkDropList
[cdkDropListAutoScrollDisabled]="true"
[cdkDropListData]="fullList"
cdkDropListLockAxis="y"
(cdkDropListDropped)="drop($event)">
<ng-container *ngFor="let item of fullList; let index = index;">
<h2 *ngIf="index === 0">List 1</h2>
<h2 *ngIf="index === numList1">List 2</h2>
<div cdkDrag class="drop-box">{{item}}</div>
</ng-container>
</div>
</div>