Angular Material 如果没有数据模型,则在列表之间拖放
Angular Material's Drag and Drop between lists if there's no data model
更新:
我创建了一个 stackblitz 来重现该问题。
考虑我拥有的以下静态模板:
<div class="websiteleftColumn" cdkDropList #left="cdkDropList"
[cdkDropListConnectedTo]="[right]">
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
</div>
<div class="websiteRightColumn" cdkDropList #right="cdkDropList"
[cdkDropListConnectedTo]="[left]">
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
</div>
我希望能够自由地重新排列两列中以及两列之间的面板。相反,我可以拖动面板,但是一旦我放下面板,什么也没有发生,它会回到原来的状态。
猜测是因为没有背后的数据模型。在 example 中,可拖动的 div 由数组中的 *ngFor
呈现在页面上。还有一个绑定到它们的 drop(event: CdkDragDrop<string[]>)
组件方法,每次发生下降时都会更新数据模型。
但我的问题是,我不仅拥有可以放入某个数组的如此简单的列表元素,而且网站的整个部分都有很多 HTML 我想拖动的代码。
如何为它创建数据模型? (如果真是Angular不见了的话)
首先连接所有列表你可以使用下面的(我不确定这是否可以解决你的拖动重置问题):
<div cdkDropListGroup>
<!-- All lists in here will be connected. -->
<div cdkDropList *ngFor="let list of lists"></div>
</div>
它应该显示在 angular 组件站点上。
您当前创建的是静态值,如果您有可以生成的动态值,那么使用 *ngFor 很可能更可取。
下拉列表中的内容将与显示的内容保持一致。因此,使用 *ngFor 您可以在单个模板上创建列表中元素的显示方式。因此,您可以在每个 dropList 中有不同的 "templates"。拥有两个下拉列表 connected/linked,您可以无论如何转移内容,但显示的内容可能与模板保持一致。
我不能确定您如何处理未定义的动态数据,但您可以对要处理的数据类型进行分类并为此创建模板。然后利用 *ngIF 并根据需要显示特定类型的数据。
查看此 for the reason why it was not working and here's also an example如何使用 ng-template
s 和数据模型正确实现拖放:
import { Component, Input, ViewChild, TemplateRef } from '@angular/core';
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
@Component({
selector: 'hello',
template: `
<div class="row" cdkDropListGroup>
<div class="col-6" cdkDropList [cdkDropListData]="list1"
(cdkDropListDropped)="panelDropped($event)">
<div cdkDrag *ngFor="let p of list1">
<ng-container *ngTemplateOutlet="this[p+'Panel']">
</ng-container>
</div>
</div>
<div class="col-6" cdkDropList [cdkDropListData]="list2"
(cdkDropListDropped)="panelDropped($event)">
<div cdkDrag *ngFor="let p of list2">
<ng-container *ngTemplateOutlet="this[p+'Panel']">
</ng-container>
</div>
</div>
</div>
<ng-template #aPanel><div class="card"></div></ng-template>
<ng-template #bPanel><div class="card"></div></ng-template>
<ng-template #cPanel><div class="card"></div></ng-template>
<ng-template #dPanel><div class="card"></div></ng-template>
<ng-template #ePanel><div class="card"></div></ng-template>
<ng-template #fPanel><div class="card"></div></ng-template>
`,
styles: [`
.col-6:nth-child(1) { background-color: plum; }
.col-6:nth-child(2) { background-color: peru; }
.card { background-color: blue; height: 10em; margin: 0.5em; }
`]
})
export class HelloComponent {
@Input() name: string;
@ViewChild('aPanel') aPanel: TemplateRef<any>;
@ViewChild('bPanel') bPanel: TemplateRef<any>;
@ViewChild('cPanel') cPanel: TemplateRef<any>;
@ViewChild('dPanel') dPanel: TemplateRef<any>;
@ViewChild('ePanel') ePanel: TemplateRef<any>;
@ViewChild('fPanel') fPanel: TemplateRef<any>;
list1: Array<string> = ['a', 'b', 'c'];
list2: Array<string> = ['d', 'e', 'f'];
panelDropped(event: CdkDragDrop<string[]>) {
if (event.previousContainer === event.container) {
moveItemInArray(event.container.data,
event.previousIndex, event.currentIndex);
} else {
transferArrayItem(event.previousContainer.data,
event.container.data, event.previousIndex, event.currentIndex);
}
}
}
更新:
我创建了一个 stackblitz 来重现该问题。
考虑我拥有的以下静态模板:
<div class="websiteleftColumn" cdkDropList #left="cdkDropList"
[cdkDropListConnectedTo]="[right]">
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
</div>
<div class="websiteRightColumn" cdkDropList #right="cdkDropList"
[cdkDropListConnectedTo]="[left]">
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
<div class="panelWithMuchContent" cdkDrag> much HTML </div>
</div>
我希望能够自由地重新排列两列中以及两列之间的面板。相反,我可以拖动面板,但是一旦我放下面板,什么也没有发生,它会回到原来的状态。
猜测是因为没有背后的数据模型。在 example 中,可拖动的 div 由数组中的 *ngFor
呈现在页面上。还有一个绑定到它们的 drop(event: CdkDragDrop<string[]>)
组件方法,每次发生下降时都会更新数据模型。
但我的问题是,我不仅拥有可以放入某个数组的如此简单的列表元素,而且网站的整个部分都有很多 HTML 我想拖动的代码。
如何为它创建数据模型? (如果真是Angular不见了的话)
首先连接所有列表你可以使用下面的(我不确定这是否可以解决你的拖动重置问题):
<div cdkDropListGroup>
<!-- All lists in here will be connected. -->
<div cdkDropList *ngFor="let list of lists"></div>
</div>
它应该显示在 angular 组件站点上。
您当前创建的是静态值,如果您有可以生成的动态值,那么使用 *ngFor 很可能更可取。
下拉列表中的内容将与显示的内容保持一致。因此,使用 *ngFor 您可以在单个模板上创建列表中元素的显示方式。因此,您可以在每个 dropList 中有不同的 "templates"。拥有两个下拉列表 connected/linked,您可以无论如何转移内容,但显示的内容可能与模板保持一致。
我不能确定您如何处理未定义的动态数据,但您可以对要处理的数据类型进行分类并为此创建模板。然后利用 *ngIF 并根据需要显示特定类型的数据。
查看此ng-template
s 和数据模型正确实现拖放:
import { Component, Input, ViewChild, TemplateRef } from '@angular/core';
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
@Component({
selector: 'hello',
template: `
<div class="row" cdkDropListGroup>
<div class="col-6" cdkDropList [cdkDropListData]="list1"
(cdkDropListDropped)="panelDropped($event)">
<div cdkDrag *ngFor="let p of list1">
<ng-container *ngTemplateOutlet="this[p+'Panel']">
</ng-container>
</div>
</div>
<div class="col-6" cdkDropList [cdkDropListData]="list2"
(cdkDropListDropped)="panelDropped($event)">
<div cdkDrag *ngFor="let p of list2">
<ng-container *ngTemplateOutlet="this[p+'Panel']">
</ng-container>
</div>
</div>
</div>
<ng-template #aPanel><div class="card"></div></ng-template>
<ng-template #bPanel><div class="card"></div></ng-template>
<ng-template #cPanel><div class="card"></div></ng-template>
<ng-template #dPanel><div class="card"></div></ng-template>
<ng-template #ePanel><div class="card"></div></ng-template>
<ng-template #fPanel><div class="card"></div></ng-template>
`,
styles: [`
.col-6:nth-child(1) { background-color: plum; }
.col-6:nth-child(2) { background-color: peru; }
.card { background-color: blue; height: 10em; margin: 0.5em; }
`]
})
export class HelloComponent {
@Input() name: string;
@ViewChild('aPanel') aPanel: TemplateRef<any>;
@ViewChild('bPanel') bPanel: TemplateRef<any>;
@ViewChild('cPanel') cPanel: TemplateRef<any>;
@ViewChild('dPanel') dPanel: TemplateRef<any>;
@ViewChild('ePanel') ePanel: TemplateRef<any>;
@ViewChild('fPanel') fPanel: TemplateRef<any>;
list1: Array<string> = ['a', 'b', 'c'];
list2: Array<string> = ['d', 'e', 'f'];
panelDropped(event: CdkDragDrop<string[]>) {
if (event.previousContainer === event.container) {
moveItemInArray(event.container.data,
event.previousIndex, event.currentIndex);
} else {
transferArrayItem(event.previousContainer.data,
event.container.data, event.previousIndex, event.currentIndex);
}
}
}