文章目录
sortablejs 是一个强大的JavaScript拖拽库。
说明
在Angular项目中使用sortablejs拖拽库时,我们需要同时使用 ngx-sortablejs 这个二次封装的Angular拖拽库,它封装了 sortablejs 指令 ,并支持以下参数:
@Directive({
selector: "[sortablejs]",
})
export class SortablejsDirective {
// 拖拽列表的数据项
@Input() sortablejs: SortableData; // array or a FormArray
// 指定拖拽的容器
@Input() sortablejsContainer: string;
// 拖拽相关的配置项
@Input() sortablejsOptions: Options;
@Input() sortablejsCloneFunction: (item: any) => any;
// 在一个拖拽实例被创建并初始化好之后,会立即emit出这个拖拽实例。
@Output() sortablejsInit = new EventEmitter<Sortable>()
}
基本使用
1. 素颜版
<div
class="container"
[sortablejs]="items"
[sortablejsOptions]="draggableOptions"
>
<div *ngFor="let item of items" class="item">
{{ item.name }}
</div>
</div>
import { SortableOptions } from 'sortablejs';
draggableOptions: SortableOptions = {};
2. 设置可被拖起的项的样式
<div
class="container"
[sortablejs]="items"
[sortablejsOptions]="draggableOptions"
>
<ng-container *ngFor="let item of items">
<div *ngIf="item.id !== '002'" class="item sortable-item">
{{ item.name }}
</div>
<div *ngIf="item.id === '002'" class="item">
{{ item.name }},这个项不可被拖起
</div>
</ng-container>
</div>
draggableOptions: SortableOptions = {
// 允许拖拽的项的类名,只有这个类名的项才可以拖起
draggable: '.sortable-item',
};
.sortable-item {
background-color: antiquewhite;
}
3. 设置被选中的项的样式
draggableOptions: SortableOptions = {
// 拖拽项被选中时的类名
chosenClass: 'sortable-chosen',
};
.sortable-chosen {
background-color: lightblue;
}
4. 设置拖拽时跟随的阴影的样式
draggableOptions: SortableOptions = {
// 项被拖拽的过程中跟随它的那个影子的类名
ghostClass: 'sortable-ghost',
};
.sortable-ghost {
background-color: lightgray;
}
5. 设置正在被拖拽中的样式
draggableOptions: SortableOptions = {
dragClass: 'sortable-drag',
};
.sortable-drag {
background-color: orange;
border-bottom: none;
}
6. 设置当前列表容器内是否可以进行拖拽排序
draggableOptions2: SortableOptions = {
sort: false, // 值为false,组内不可拖拽排序
group: {
name: 'china',
pull: true, // 组内的项可以被拖出去到其它组
}
};
7. 设置拖拽的手柄
<div
class="container"
[sortablejs]="items"
[sortablejsOptions]="draggableOptions"
>
<div *ngFor="let item of items" class="item sortable-item">
<div class="sortable-handle">手柄</div>
{{ item.name }}
</div>
</div>
draggableOptions: SortableOptions = {
// draggable: '.sortable-item',
// 可拖拽项的手柄的类名,只有按住手柄才能拖起。(如果将上面那行注释放开,那就不只有手柄能拖拽了)
handle: '.sortable-handle',
};
8. 多个列表之间的拖拽 [group]
示例1 [name]
配置项的group属性里的name相同的两个拖拽组之间的项可以互相拖拽。
// 甲组
draggableOptions1: SortableOptions = {
group: {
name: 'wmm',
}
};
// 乙组
draggableOptions2: SortableOptions = {
group: {
name: 'wmm',
}
};
示例2 [put]
多个拖拽组,name不同时,可以通过 put 指定其它组只有满足条件的项可以拖进当前列表。
// 甲组
draggableOptions1: SortableOptions = {
group: {
name: 'wmm',
}
};
// 乙组
draggableOptions2: SortableOptions = {
group: {
name: 'china',
}
};
// 丙组
draggableOptions3: SortableOptions = {
group: {
name: 'happy',
/**
* put字段的值可以指定为以下四种:
* true: 可以将其它指定组的项拖进本组
* false: 其它任何组的项都不能拖到本组
* ['wmm', 'china']: 只能将甲组和乙组的项拖到本组。['china']: 只能将乙组的项拖到本组。
* function: 自定义函数,可进行复杂逻辑判断,根据返回true或false,来判断当前被拖拽的项是否能往本组里放。
*/
put: ['china'], // 指定甲组和乙组的项可以往丙组里面放
}
};
示例3 [put function]
多个拖拽组,可以通过指定 put 的值为function,在function里进行复杂判断来确定被拖拽的项是否可以被拖进本组。
<div
class="container2"
[sortablejs]="items2"
[sortablejsOptions]="draggableOptions2"
>
乙组
<div
*ngFor="let item of items2"
class="item sortable-item2"
[ngClass]="{
'can-move-to-happy': item.name.indexOf('乙 5') === -1
}"
>
{{ item.name }}
{{ item.name.indexOf("乙 5") !== -1 ? "--该项不可用被拖进丙组" : "" }}
</div>
</div>
// 乙组
draggableOptions2: SortableOptions = {
group: {
name: 'china',
}
};
// 丙组
draggableOptions3: SortableOptions = {
group: {
name: 'happy',
/**
* put的值可以是一个自定义function,可进行复杂逻辑判断。
* 根据返回true或false,来判断当前被拖拽的项是否能往本组里放。
*/
put: (
to: Sortable,
from: Sortable,
dragEl: HTMLElement,
event: SortableEvent
) => {
// 判断:只有带有样式类名为'can-move-to-happy'的项,才能被拖进本组。
return dragEl?.classList.contains('can-move-to-happy');
},
}
};
示例4 [pull]
draggableOptions2: SortableOptions = {
group: {
name: 'china',
/**
* 从一个列表中拖动到另一个列表时,是否允许拖动。 默认值:true。
* true:允许拖动
* false:不允许拖动
* 'clone':克隆一个副本拖到其它组
* function:自定义函数,可进行复杂逻辑判断,根据返回true或false,来判断被拖拽的项是否可从本组移出去。
*/
pull: (
to: Sortable,
from: Sortable,
dragEl: HTMLElement,
event: SortableEvent
) => {
return !dragEl?.classList.contains('can-move-to-happy');
},
},
};
此示例就不截图了。
9. 多个拖拽组嵌套
<div
class="grandpa-container"
[sortablejs]="treeItems"
[sortablejsOptions]="draggableOptions"
>
<div
*ngFor="let grandpa of treeItems"
class="item"
[id]="grandpa.id"
[ngClass]="{
a: grandpa.name.indexOf('甲') !== -1,
b: grandpa.name.indexOf('乙') !== -1,
c: grandpa.name.indexOf('丙') !== -1
}"
>
{{ grandpa?.name }}
<ng-container *ngIf="grandpa?.children?.length">
<div
class="father-container"
[id]="grandpa.id"
[sortablejs]="grandpa?.children"
[sortablejsOptions]="draggableOptions"
>
<div
*ngFor="let father of grandpa?.children"
class="item"
[id]="father.id"
[ngClass]="{
a: father.name.indexOf('甲') !== -1,
b: father.name.indexOf('乙') !== -1,
c: father.name.indexOf('丙') !== -1
}"
>
{{ father?.name }}
<ng-container *ngIf="father?.children?.length">
<div
class="son-container"
[id]="father.id"
[sortablejs]="father?.children"
[sortablejsOptions]="draggableOptions"
>
<div
*ngFor="let son of father?.children"
class="item"
[id]="son.id"
[ngClass]="{
a: son.name.indexOf('甲') !== -1,
b: son.name.indexOf('乙') !== -1,
c: son.name.indexOf('丙') !== -1
}"
>
{{ son?.name }}
</div>
</div>
</ng-container>
</div>
</div>
</ng-container>
</div>
</div>
public draggableOptions: SortableOptions = {
group: {
name: 'wmm',
}
// 元素 从其它拖拽分组 拖进 本拖拽分组 时触发
onAdd: (event: SortableEvent) => {
console.log('onAdd event:', event);
console.log('自身id:', event.item.id);
console.log('当前所属父id:', event.to.id);
console.log('在当前分组中的index:', event.newIndex);
},
// 元素在本拖拽分组中的位置发生改变时触发
onUpdate: (event: SortableEvent) => {
console.log('onUpdate event:', event);
},
};
public treeItems: {
id: string;
name: string;
children?: any[] = [];
} = [];
ngOnInit(): void {
// 初始化 treeItems
for (let i = 0; i < 5; i++) {
let grandpa: any = { id: `0${i}`, name: `甲 0${i}`, children: [] };
if (i === 1) {
let fathers: any = [];
for (let j = 0; j < 5; j++) {
const fatherItem: any = {
id: `00${j}`,
name: `乙 00${j}`,
};
if (j === 4) {
let sons: any = [];
for (let k = 0; k < 5; k++) {
const sonItem = {
id: `000${k}`,
name: `丙 000${k}`,
};
sons.push(sonItem);
}
fatherItem.children = sons;
}
fathers.push(fatherItem);
}
grandpa.children = fathers;
}
this.treeItems.push(grandpa);
}
}
第一次拖拽:
第二次拖拽:
学习来源
更多配置项及回调方法: http://www.sortablejs.com/options.html
更多示例: http://sortablejs.github.io/Sortable/
Sortable仓库: https://github.com/SortableJS/Sortable
ngx-sortablejs仓库 https://github.com/sortablejs/ngx-sortablejs#readme