Skip to content

Commit 26e93cc

Browse files
authored
feat(abc:st): add drag property (#1876)
1 parent e28a21a commit 26e93cc

File tree

11 files changed

+133
-7
lines changed

11 files changed

+133
-7
lines changed

packages/abc/st/demo/drag.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
order: 4
3+
title:
4+
en-US: Drag sorting
5+
zh-CN: 拖拽排序
6+
---
7+
8+
## zh-CN
9+
10+
使用 `drag` 实现行拖拽排序。
11+
12+
## en-US
13+
14+
Use `drag` to implement row drag sorting.
15+
16+
```ts
17+
import { Component } from '@angular/core';
18+
19+
import { STColumn, STData, STModule } from '@delon/abc/st';
20+
21+
@Component({
22+
selector: 'app-demo',
23+
template: `<st [data]="users" [columns]="columns" drag />`,
24+
imports: [STModule]
25+
})
26+
export class DemoComponent {
27+
users: STData[] = Array(10)
28+
.fill({})
29+
.map((_, idx) => {
30+
return {
31+
id: idx + 1,
32+
name: `name ${idx + 1}`,
33+
age: Math.ceil(Math.random() * 10) + 20
34+
};
35+
});
36+
columns: STColumn[] = [
37+
{ title: '编号4', index: 'id' },
38+
{ title: '编号5', index: 'id' },
39+
{ title: '编号6', index: 'id' },
40+
{ title: '编号7', index: 'id' },
41+
{ title: '编号8', index: 'id' },
42+
{ title: '编号8', index: 'id' },
43+
{ title: '编号8', index: 'id' },
44+
{ title: '编号8', index: 'id' },
45+
{ title: '编号8', index: 'id' }
46+
];
47+
}
48+
```

packages/abc/st/index.en-US.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ When an exception is thrown when parsing column data, *INVALID DATA* will be for
8888
| `[responsiveHideHeaderFooter]` | Whether to display the header and footer under the small screen | `boolean` | `false` ||
8989
| `[resizable]` | Resize header of the current table, **Multiple headers not supported** | `STResizable, boolean` | - | - |
9090
| `[trackBy]` | `TrackByFunction` function of list loop `@for` | `TrackByFunction<T>` | - | - |
91+
| `[drag]` | Drag soring | `STDragOptions, boolean` | - | - |
9192
| `(change)` | Events | `EventEmitter<STChange>` | - | - |
9293
| `(error)` | Error event | `EventEmitter<STError>` | - | - |
9394

packages/abc/st/index.zh-CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ module: import { STModule } from '@delon/abc/st';
8888
| `[responsiveHideHeaderFooter]` | 是否在小屏幕下才显示顶部与底部 | `boolean` | `false` ||
8989
| `[resizable]` | 当前表格所有列的调整表头配置项,**不支持多表头** | `STResizable, boolean` | - | - |
9090
| `[trackBy]` | `@for` 列表循环的 `TrackByFunction` 函数 | `TrackByFunction<T>` | - | - |
91+
| `[drag]` | 拖拽排序 | `STDragOptions, boolean` | - | - |
9192
| `(change)` | 变化时回调,包括:`pi``ps``checkbox``radio``sort``filter``click``dblClick``expand` 变动 | `EventEmitter<STChange>` | - | - |
9293
| `(error)` | 异常时回调 | `EventEmitter<STError>` | - | - |
9394

packages/abc/st/st.component.html

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,15 @@
145145
}
146146
</thead>
147147
}
148-
<tbody class="st__body">
148+
<tbody
149+
class="st__body"
150+
cdkDropList
151+
[cdkDropListDisabled]="drag() === null"
152+
(cdkDropListDropped)="drag()?.dropped?.($event)"
153+
(cdkDropListEntered)="drag()?.entered?.($event)"
154+
(cdkDropListExited)="drag()?.exited?.($event)"
155+
(cdkDropListSorted)="drag()?.sorted?.($event)"
156+
>
149157
@if (!_loading) {
150158
<ng-template [ngTemplateOutlet]="bodyHeader!" [ngTemplateOutletContext]="{ $implicit: _statistical }" />
151159
}
@@ -155,6 +163,7 @@
155163
(click)="_rowClick($event, i, index, false)"
156164
(dblclick)="_rowClick($event, i, index, true)"
157165
[class]="i._rowClassName"
166+
cdkDrag
158167
>
159168
@if (expand) {
160169
<td

packages/abc/st/st.component.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
12
import type { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
23
import { DecimalPipe, DOCUMENT, NgTemplateOutlet } from '@angular/common';
34
import {
@@ -10,6 +11,7 @@ import {
1011
ElementRef,
1112
EventEmitter,
1213
inject,
14+
input,
1315
Input,
1416
numberAttribute,
1517
OnChanges,
@@ -72,6 +74,7 @@ import type {
7274
STContextmenuItem,
7375
STCustomRequestOptions,
7476
STData,
77+
STDragOptions,
7578
STError,
7679
STExportOptions,
7780
STLoadOptions,
@@ -251,7 +254,8 @@ export class STTdComponent {
251254
NzIconDirective,
252255
NzMenuModule,
253256
STFilterComponent,
254-
STTdComponent
257+
STTdComponent,
258+
DragDropModule
255259
]
256260
})
257261
export class STComponent implements AfterViewInit, OnChanges {
@@ -330,6 +334,20 @@ export class STComponent implements AfterViewInit, OnChanges {
330334
@Input({ transform: booleanAttribute }) bordered = false;
331335
@Input() size!: 'small' | 'middle' | 'default';
332336
@Input() scroll: { x?: string | null; y?: string | null } = { x: null, y: null };
337+
drag = input<STDragOptions | null, STDragOptions | boolean | string | null | undefined>(null, {
338+
transform: v => {
339+
const obj: STDragOptions | null = typeof v === 'object' ? v : booleanAttribute(v) ? {} : null;
340+
if (obj == null) return null;
341+
342+
if (typeof obj.dropped !== 'function') {
343+
obj.dropped = e => {
344+
moveItemInArray(this._data, e.previousIndex, e.currentIndex);
345+
this.cd();
346+
};
347+
}
348+
return obj;
349+
}
350+
});
333351
@Input() singleSort?: STSingleSort | null;
334352
private _multiSort?: STMultiSort;
335353
@Input()

packages/abc/st/st.interfaces.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
2-
import { HttpHeaders, HttpParams } from '@angular/common/http';
3-
import { ElementRef, TemplateRef } from '@angular/core';
4-
import { Observable } from 'rxjs';
2+
import type { CdkDragDrop, CdkDragEnter, CdkDragExit, CdkDragSortEvent } from '@angular/cdk/drag-drop';
3+
import type { HttpHeaders, HttpParams } from '@angular/common/http';
4+
import type { ElementRef, TemplateRef } from '@angular/core';
5+
import type { Observable } from 'rxjs';
56

67
import type { ThemeType } from '@ant-design/icons-angular';
78

@@ -1316,3 +1317,25 @@ export interface STOnCellResult {
13161317
rowSpan?: number | null;
13171318
colSpan?: number | null;
13181319
}
1320+
1321+
export interface STDragOptions {
1322+
/**
1323+
* Emits when the user drops an item inside the container, default: `moveItemInArray()`
1324+
*/
1325+
dropped?: (e: CdkDragDrop<any, any, any>) => void;
1326+
1327+
/**
1328+
* Emits when the user has moved a new drag item into this container.
1329+
*/
1330+
entered?: (e: CdkDragEnter<any>) => void;
1331+
1332+
/**
1333+
* Emits when the user removes an item from the container by dragging it into another container.
1334+
*/
1335+
exited?: (e: CdkDragExit<any>) => void;
1336+
1337+
/**
1338+
* Emits as the user is swapping items while actively dragging.
1339+
*/
1340+
sorted?: (e: CdkDragSortEvent<any>) => void;
1341+
}

packages/abc/st/test/base.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
STColumnTitle,
2929
STContextmenuFn,
3030
STCustomRequestOptions,
31+
STDragOptions,
3132
STError,
3233
STMultiSort,
3334
STPage,
@@ -427,6 +428,7 @@ export class PageObject<T extends TestComponent> {
427428
[showHeader]="showHeader"
428429
[contextmenu]="contextmenu"
429430
[customRequest]="customRequest"
431+
[drag]="drag"
430432
(change)="change($event)"
431433
(error)="error($event)"
432434
/>
@@ -470,6 +472,8 @@ export class TestComponent {
470472
{ text: 'b', children: [{ text: 'c', fn: jasmine.createSpy() }] }
471473
];
472474

475+
drag?: STDragOptions | boolean = false;
476+
473477
error(): void {}
474478
change(): void {}
475479
}

packages/abc/st/test/st.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,14 @@ describe('abc: st', () => {
15911591
page.asyncEnd();
15921592
}));
15931593
});
1594+
describe('#drag', () => {
1595+
it('should be working', fakeAsync(() => {
1596+
page.updateColumn([{ title: 'a', index: 'id' }]).expectElCount('.cdk-drop-list-disabled', 1);
1597+
context.drag = {};
1598+
fixture.detectChanges();
1599+
page.updateColumn([{ title: 'a', index: 'id' }]).expectElCount('.cdk-drop-list-disabled', 0);
1600+
}));
1601+
});
15941602
});
15951603
describe('[custom render template]', () => {
15961604
it('with column title', fakeAsync(() => {

packages/theme/system/ng/_drag.less

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.cdk-drag {
2+
&-preview {
3+
display: table;
4+
}
5+
6+
&-placeholder {
7+
opacity: 0;
8+
}
9+
}

packages/theme/system/ng/index.less

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
@import './_preserve-white-spaces.less';
22
@import './_form.less';
3+
@import './_drag.less';

0 commit comments

Comments
 (0)