angular6.x--拖拽、排序

app.modules.ts导入

import { DragDropModule } from '@angular/cdk/drag-drop';

imports: [
  ...
  DragDropModule
]

html:

<div cdkDrag class="drag-box"
drag me
</div>

1.排序
html:

<h3>列表排序</h3>
<div class="box-list" cdkDropList (cdkDropListDropped)="drop($event)">
<div class="drag-box" *ngFor="let customer of customers" cdkDrag>
{{customer.name}}
</div>
</div>

ts:

import { ...CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';

customers = [
{ name: 'Adam', age: 23 },
{ name: 'Jack', age: 27 },
{ name: 'Katherin', age: 26 },
{ name: 'John', age: 30 },
{ name: 'Watson', age: 42 },
];

drop(event: CdkDragDrop<string[]>) {
console.log('列表排序:', event, this.customers);
moveItemInArray(this.customers, event.previousIndex, event.currentIndex);
}

image.png

打印结果:
image.png

2.横向列表排序

<h3>横向排序</h3>
<div class="box-list-horizontal" cdkDropList cdkDropListOrientation="horizontal" (cdkDropListDropped)="drop($event)">
  <div class="drag-box" *ngFor="let customer of customers" cdkDrag>
    {{customer.name}}
  </div>
</div>

3.动画效果
为了设置动画,我们定义了一个以transform属性为目标的转换。拖放CDK支持动画:
--对列表中的元素进行拖动排序时的动画=> .cdk-drag

.cdk-drag {
transition: transform 100ms ease;
}

--从动画的位置到最终把它放在列表的位置上时的动画=> .cdk-drag-animating

.cdk-drag-animating {
transition: transform 300ms ease;
}

4.占位符元素 placeholder
默认占位符:
使用.cdk-drag-placeholder来显示占位符元素,而不是实际的元素,因为它是在cdkDropList中拖动的。默认情况下,这看起来与正在排序的元素完全相同。

.cdk-drag-placeholder {
background: #ccc;
border: dotted 1px #999;
transition: transform 500ms ease;
}

image.png

自定义占位符 Custom placeholder:
使用*cdkDragPlaceholder指令,我们可以用一个自定义的占位符来代替默认的占位符:

<div class="box-list customph" cdkDropList (cdkDropListDropped)="drop($event)">
  <div class="drag-box dragList" *ngFor="let customer of customers" cdkDrag >
    <div class="box-custom-placeholder" *cdkDragPlaceholder></div>
    {{customer.name}}
  </div>
</div>
// 自定义占位符
.customph{
  .box-custom-placeholder {
    height: 28px;
    width: 100px;
    background: #fff;
    border: dotted 1px #0084ff;
    transition: transform 200ms ease;
  }
  &.box-list.cdk-drop-list-dragging .drag-box:not(.cdk-drag-placeholder) {
    transition: transform 500ms ease;
  }
}

5.预览
当提取并拖动cdkDrag元素时,可以看到预览元素。默认情况下,预览元素看起来与被拖动的元素完全相同。
使用.cdk-drag-preview来定义预览CSS:

.cdk-drag-preview {
height: 28px;
width: 100px;
box-shadow: 0 3px 3px -3px #0084ff;
}

我们还需要使用*cdkDragPreview提供一个自定义模板:

<div cdkDropList class="box-list" (cdkDropListDropped)="drop($event)">
<div class="drag-box dragList" *ngFor="let customer of customers" cdkDrag>
{{customer.name}}
<p *cdkDragPreview>Age: {{customer.age}}</p>
</div>
</div>

6.在列表之间拖放
我们可以使用cdkDropListConnectedTo属性将一个或多个cdkDropList连接到一起。然后设置cdkDropListData和cdkDragData,将数据与cdkDropList和cdkDrag关联起来。

<div class="box-list" cdkDropList #inactiveList="cdkDropList" id = "Inactive Customers"
  [cdkDropListData]="inactiveCustomers" [cdkDropListConnectedTo]="[activeList]"
  (cdkDropListDropped)="drop1($event)">
  <div
    class="drag-box dragList"
    [cdkDragData]="customer"
    *ngFor="let customer of inactiveCustomers" 
    cdkDrag>
      {{customer}}
  </div>
</div>
<div class="box-list" cdkDropList #activeList="cdkDropList" id = "Active Customers"
  [cdkDropListData]="activeCustomers" [cdkDropListConnectedTo]="[inactiveList]"
  (cdkDropListDropped)="drop1($event)">
   <div
     class="drag-box dragList"
     [cdkDragData]="customer"
     *ngFor="let customer of activeCustomers" 
     cdkDrag>
       {{customer}}
   </div>
</div>
import { ...transferArrayItem } from '@angular/cdk/drag-drop';
inactiveCustomers = [
'Adam',
'Jack',
'Katherin'
];

activeCustomers = [
'John',
'Watson'
];
drop1(event: CdkDragDrop<string[]>) {
  console.log('拖拽事件:event', event);
  if (event.previousContainer === event.container) {
  console.log('拖拽事件',`> 拖 '${event.item.data}' 到 '${event.container.id}'`);
  moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
  } else {
    console.log('拖拽事件',`> 拖 '${event.item.data}' 到 '${event.container.id}'`);
    transferArrayItem(event.previousContainer.data, event.container.data,event.previousIndex, event.currentIndex);
  }
}
image.png

image.png

image.png

image.png

dkDropListGroup
CdkDropListGroup指令的范围比CdkDropList要大一级。CdkDropListGroup可以包含多个CdkDropList。而且当CdkDropListGroup包含多个CdkDropList的时候,这些CdkDropList直接是相互connect的(CdkDropList就不用去写cdkDropListConnectedTo属性了)。

<div cdkDropListGroup>
  <div class="box-list" cdkDropList id = "Inactive Customers"
    [cdkDropListData]="inactiveCustomers" 
    (cdkDropListDropped)="drop1($event)">
  <div class="drag-box dragList" [cdkDragData]="customer"
    *ngFor="let customer of inactiveCustomers" cdkDrag>
    {{customer.name}}
  </div>
</div>
  <div class="box-list" cdkDropList id = "Active Customers"
    [cdkDropListData]="activeCustomers" 
    (cdkDropListDropped)="drop1($event)">
    <div
      class="drag-box dragList"
      [cdkDragData]="customer"
      *ngFor="let customer of activeCustomers" 
      cdkDrag>
        {{customer.name}}
    </div>
  </div>
</div>

7.事件监听
Drag Event Handlers
– cdkDragStarted: 当用户开始拖动时发出。
– cdkDragEnded: 当用户停止拖动时发出。
– cdkDragEntered: 将item移动到新容器中时发出。
– cdkDragExited: 将item移出当前容器时发出。

<h3>事件监听</h3>
<div cdkDrag class="drag-box"
(cdkDragStarted)="dragStarted($event)"
(cdkDragEnded)="dragEnded($event)"
(cdkDragMoved)="dragMoved($event)"
>
drag me
</div>
<p>{{state}} {{position}}</p>
import { CdkDragEnd, CdkDragStart, CdkDragMove... } from '@angular/cdk/drag-drop';
dragStarted(event: CdkDragStart) {
this.state = '拖拽开始';
console.log('拖拽开始');
}

dragEnded(event: CdkDragEnd) {
this.state = '拖拽结束';
console.log('拖拽结束');
}

dragMoved(event: CdkDragMove) {
console.log('dragMoved');
this.position = `> Position X: ${event.pointerPosition.x} - Y: ${event.pointerPosition.y}`;
}

Drop Event Handlers
– cdkDropListDropped: emits when an item was dropped inside the container.
– cdkDropListEntered: emits when a new item is dragged into this container.
– cdkDropListExited: emits when an item is dragged from this container into another container.

<div class="box-list" cdkDropList #inactiveList="cdkDropList" id = "Inactive Customers"
[cdkDropListData]="inactiveCustomers" [cdkDropListConnectedTo]="[activeList]"
(cdkDropListDropped)="drop1($event)"
(cdkDropListEntered)="dropListEntered($event)" (cdkDropListExited)="dropListExited($event)"
>
<div class="drag-box dragList" [cdkDragData]="customer"
(cdkDragEntered)="dragEntered($event)" (cdkDragExited)="dragExited($event)"
*ngFor="let customer of inactiveCustomers" 
cdkDrag>
{{customer}}
</div>
</div>
<div class="box-list" cdkDropList #activeList="cdkDropList" id = "Active Customers"
[cdkDropListData]="activeCustomers" [cdkDropListConnectedTo]="[inactiveList]"
(cdkDropListDropped)="drop1($event)">
<div
class="drag-box dragList"
[cdkDragData]="customer"
*ngFor="let customer of activeCustomers" 
cdkDrag>
{{customer}}
</div>
</div>
import { ...CdkDragEnter, CdkDragExit} from '@angular/cdk/drag-drop';
dragEntered(event: CdkDragEnter) {
console.log(`drag:把 '${event.item.data}' 拖进 '${event.container.id}' `);
}

dragExited(event: CdkDragExit) {
console.log(`drag:把 '${event.item.data}' 从 '${event.container.id}' 中拖出 `);
}

dropListEntered(event: CdkDragEnter) {
console.log(`drop:'${event.container.id}' 中拖进了 '${event.item.data}'`);
}

dropListExited(event: CdkDragExit) {
console.log(`drop:从 '${event.container.id}' 中拖出 '${event.item.data}'`);
}

执行如下操作


image.png

打印结果:


image.png

再執行如下操作:
image.png

打印结果:


image.png

cdkDropListSorted
拖拽过程中交换item的时候回调

<div class="box-list" cdkDropList #activeList="cdkDropList" id = "Active Customers"
[cdkDropListData]="activeCustomers" [cdkDropListConnectedTo]="[inactiveList]"
(cdkDropListDropped)="drop1($event)" 
(cdkDropListSorted)="dropListSorted($event)"
>
<div
class="drag-box dragList"
[cdkDragData]="customer"
*ngFor="let customer of activeCustomers" 
cdkDrag>
{{customer.name}}
</div>
</div>
dropListSorted(event: CdkDropList) {
console.log('Sorted:', event);
}

cdkDropListEnterPredicate
enterPredicate: (drag: CdkDrag, drop: CdkDropList) => boolean
指定哪些item是可以拖拽到当前容器

<div class="box-list" cdkDropList #activeList="cdkDropList" id = "Active Customers"
[cdkDropListData]="activeCustomers" [cdkDropListConnectedTo]="[inactiveList]"
(cdkDropListDropped)="drop1($event)" [cdkDropListEnterPredicate]="predicate"
>
<div
class="drag-box dragList"
[cdkDragData]="customer"
*ngFor="let customer of activeCustomers" 
cdkDrag>
{{customer.name}}
</div>
</div>
import { ...CdkDrag, CdkDropList } from '@angular/cdk/drag-drop';
predicate(drag: CdkDrag, drop: CdkDropList) {
console.log('predicate:', drag, drop);
return drag.data.age >= 18;
}

CdkDrag

image.png

CdkDropList
image.png

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,547评论 4 374
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,787评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,175评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,752评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,169评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,056评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,195评论 2 321
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,980评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,724评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,872评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,344评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,667评论 3 264
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,379评论 3 245
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,202评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,992评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,189评论 2 286
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,987评论 2 279