@hinen/pro-element-plus 1.8.5 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/DataTable/DataTable.vue.d.ts +72 -507
- package/dist/components/DataTable/DataTable.vue.d.ts.map +1 -1
- package/dist/components/DataTable/SelectionBar.vue.d.ts +54 -0
- package/dist/components/DataTable/SelectionBar.vue.d.ts.map +1 -0
- package/dist/components/DataTable/defineDataTableColumns.d.ts +2 -2
- package/dist/components/DataTable/defineDataTableColumns.d.ts.map +1 -1
- package/dist/components/DataTable/defineDataTableEnabled.d.ts.map +1 -1
- package/dist/components/DataTable/defineDataTableInitialData.d.ts +2 -2
- package/dist/components/DataTable/defineDataTableInitialData.d.ts.map +1 -1
- package/dist/components/DataTable/defineDataTablePlaceholderData.d.ts +2 -2
- package/dist/components/DataTable/defineDataTablePlaceholderData.d.ts.map +1 -1
- package/dist/components/DataTable/defineDataTableQueryFn.d.ts +2 -2
- package/dist/components/DataTable/defineDataTableQueryFn.d.ts.map +1 -1
- package/dist/components/DataTable/defineDataTableQueryKey.d.ts.map +1 -1
- package/dist/components/DataTable/props.d.ts +1 -186
- package/dist/components/DataTable/props.d.ts.map +1 -1
- package/dist/components/DataTable/types.d.ts +69 -41
- package/dist/components/DataTable/types.d.ts.map +1 -1
- package/dist/components/DataTable/useDataTable.d.ts +6 -14
- package/dist/components/DataTable/useDataTable.d.ts.map +1 -1
- package/dist/components/DataTable/utils.d.ts +5 -1
- package/dist/components/DataTable/utils.d.ts.map +1 -1
- package/dist/components/Drawer/Drawer.vue.d.ts +1 -1
- package/dist/index.cjs +29 -29
- package/dist/index.js +3023 -3399
- package/dist/skills/using-data-table/SKILL.md +26 -28
- package/dist/skills/using-data-table/references/examples.md +51 -50
- package/dist/skills/using-data-table/references/gotchas.md +18 -48
- package/dist/skills/using-data-table/references/props.md +36 -17
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/dist/components/DataTable/DataTable.test.d.ts +0 -2
- package/dist/components/DataTable/DataTable.test.d.ts.map +0 -1
|
@@ -77,7 +77,8 @@ If not, a simpler table or a standalone form is usually a better fit.
|
|
|
77
77
|
4. Use `useDataTable()` only when parent code truly needs imperative control.
|
|
78
78
|
|
|
79
79
|
5. Treat selection and highlight as independent concerns.
|
|
80
|
-
Use `selection.mode` to control selection UI: `'single'` for radio-driven single selection, `'multiple'` for checkbox-driven multi selection
|
|
80
|
+
Use `selection.mode` to control selection UI: `'single'` for radio-driven single selection, `'multiple'` for checkbox-driven multi selection.
|
|
81
|
+
Selection columns only appear when a `{ type: 'selection' }` column is present in `columns`.
|
|
81
82
|
Use `highlightCurrentRow` separately to enable native row highlighting, independent of selection mode.
|
|
82
83
|
|
|
83
84
|
## Minimal patterns
|
|
@@ -156,27 +157,24 @@ Common methods:
|
|
|
156
157
|
- `setCurrentPage()`
|
|
157
158
|
- `setPageSize()`
|
|
158
159
|
- `clearSelection()`
|
|
160
|
+
- `setSelectionRows(rows)`
|
|
161
|
+
- `getSelectedRow()`
|
|
159
162
|
- `getDataSource()`
|
|
160
163
|
- `refresh()` / `refetch()` in remote mode only
|
|
161
164
|
|
|
162
165
|
Use this pattern when toolbars, tabs, route sync, or external controls need to coordinate the table.
|
|
163
166
|
|
|
164
|
-
- `
|
|
165
|
-
- `
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
- use `setCurrentRow(row)` to select a row programmatically
|
|
170
|
-
- use `setCurrentRow()` to clear the current single-select row
|
|
171
|
-
- use `currentRowKey` together with `rowKey` for controlled current-row sync
|
|
172
|
-
- do not rely on row clicks to change the current row when single-select mode is active
|
|
167
|
+
- `getSelectionRows()` returns all selected rows across pages (full row objects)
|
|
168
|
+
- `setSelectionRows(rows)` sets selection programmatically (accepts full row objects)
|
|
169
|
+
- `getSelectedRow()` returns the first selected row (works for both single and multi select)
|
|
170
|
+
- `clearSelection()` clears all selection
|
|
173
171
|
|
|
174
172
|
## Controlled selection mode
|
|
175
173
|
|
|
176
174
|
`DataTable` supports two selection modes:
|
|
177
175
|
|
|
178
176
|
1. **Internal mode** — the component owns selection state (default)
|
|
179
|
-
2. **Controlled mode** — parent state owns selection via `v-model:
|
|
177
|
+
2. **Controlled mode** — parent state owns selection via `v-model:selectionRows`
|
|
180
178
|
|
|
181
179
|
### Internal mode
|
|
182
180
|
|
|
@@ -190,14 +188,14 @@ Use internal mode when the page does not need to read or manipulate selection fr
|
|
|
190
188
|
|
|
191
189
|
Use controlled mode when parent code needs to:
|
|
192
190
|
|
|
193
|
-
- read selected row
|
|
191
|
+
- read selected row objects reactively
|
|
194
192
|
- set selection from external state
|
|
195
193
|
- sync selection with URL, storage, or other components
|
|
196
194
|
- clear or modify selection programmatically
|
|
197
195
|
|
|
198
196
|
```vue
|
|
199
197
|
<DataTable
|
|
200
|
-
v-model:
|
|
198
|
+
v-model:selectionRows="selectedRows"
|
|
201
199
|
:columns="columns"
|
|
202
200
|
:query-fn="queryFn"
|
|
203
201
|
:selection="{ mode: 'multiple' }"
|
|
@@ -205,36 +203,37 @@ Use controlled mode when parent code needs to:
|
|
|
205
203
|
```
|
|
206
204
|
|
|
207
205
|
```ts
|
|
208
|
-
const
|
|
206
|
+
const selectedRows = ref<any[]>([]);
|
|
209
207
|
|
|
210
208
|
// Read selection
|
|
211
|
-
console.log(
|
|
209
|
+
console.log(selectedRows.value);
|
|
212
210
|
|
|
213
211
|
// Set selection
|
|
214
|
-
|
|
212
|
+
selectedRows.value = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
|
|
215
213
|
|
|
216
214
|
// Clear selection
|
|
217
|
-
|
|
215
|
+
selectedRows.value = [];
|
|
218
216
|
```
|
|
219
217
|
|
|
220
218
|
### Key differences
|
|
221
219
|
|
|
222
220
|
| Aspect | Internal mode | Controlled mode |
|
|
223
221
|
| ----------------- | ----------------------- | -------------------------------------------- |
|
|
224
|
-
| State owner | `DataTable` internal | Parent via `
|
|
225
|
-
| Prop | none | `v-model:
|
|
226
|
-
| Emit | `selectionChange` | `selectionChange` + `update:
|
|
227
|
-
| Initial selection |
|
|
222
|
+
| State owner | `DataTable` internal | Parent via `selectedRows` |
|
|
223
|
+
| Prop | none | `v-model:selectionRows` |
|
|
224
|
+
| Emit | `selectionChange` | `selectionChange` + `update:selectionRows` |
|
|
225
|
+
| Initial selection | `initialSelectionRows` | controlled by parent |
|
|
228
226
|
| Clear from parent | call `clearSelection()` | set model to `[]` |
|
|
229
227
|
|
|
230
228
|
### Important notes
|
|
231
229
|
|
|
232
|
-
- `
|
|
233
|
-
- When `v-model:
|
|
230
|
+
- `selectionRows` is typed as `any[]` (array of full row objects)
|
|
231
|
+
- When `v-model:selectionRows` is provided, the component operates in controlled mode
|
|
234
232
|
- The `selection` prop remains for customization only, never for state control
|
|
235
233
|
- Cross-page selection requires `rowKey` in both modes
|
|
236
|
-
- Instance methods like `getSelectionRows()`, `toggleRowSelection()` still work in controlled mode
|
|
234
|
+
- Instance methods like `getSelectionRows()`, `setSelectionRows()`, `toggleRowSelection()` still work in controlled mode
|
|
237
235
|
- `clearSelection()` still clears the internal selection, but in controlled mode you should update the parent state instead
|
|
236
|
+
- Single-select mode returns an array with 0 or 1 element, multi-select returns 0..N elements
|
|
238
237
|
|
|
239
238
|
## Slots
|
|
240
239
|
|
|
@@ -272,13 +271,12 @@ For checkbox selection review:
|
|
|
272
271
|
- Ignoring `enabled` when queries depend on prerequisites
|
|
273
272
|
- Accidentally hiding pagination through `hidePaginationWhenEmpty`
|
|
274
273
|
- Assuming `success` is optional in remote mode
|
|
275
|
-
- Expecting cross-page
|
|
274
|
+
- Expecting cross-page selection state without `rowKey`
|
|
276
275
|
- Assuming the `selectionBar` slot keeps the built-in review UI
|
|
277
276
|
- Treating `selectionBar.reviewPopoverProps` as item-render customization instead of popover-container customization
|
|
278
277
|
- Treating `highlightCurrentRow` as a selection-mode prop instead of a pure highlight switch
|
|
279
|
-
-
|
|
280
|
-
-
|
|
281
|
-
- Using `row-selection` prop (it does not exist; use `selection.mode` instead)
|
|
278
|
+
- Using `selectedRowKeys` (it has been replaced by `selectionRows` which uses full row objects)
|
|
279
|
+
- Expecting `selectionRows` to be required (non-controlled mode is fully supported)
|
|
282
280
|
|
|
283
281
|
## Related skills
|
|
284
282
|
|
|
@@ -179,15 +179,15 @@ Recommended pattern:
|
|
|
179
179
|
|
|
180
180
|
Use the `selectionBar` slot only when the page should replace the built-in review UI completely.
|
|
181
181
|
|
|
182
|
-
## 12. Controlled selection with v-model:
|
|
182
|
+
## 12. Controlled selection with v-model:selectionRows
|
|
183
183
|
|
|
184
|
-
Use `v-model:
|
|
184
|
+
Use `v-model:selectionRows` when parent state should control selection.
|
|
185
185
|
|
|
186
186
|
Minimal pattern:
|
|
187
187
|
|
|
188
188
|
```vue
|
|
189
189
|
<DataTable
|
|
190
|
-
v-model:
|
|
190
|
+
v-model:selectionRows="selectedRows"
|
|
191
191
|
:columns="columns"
|
|
192
192
|
:query-fn="queryFn"
|
|
193
193
|
row-key="id"
|
|
@@ -197,43 +197,43 @@ Minimal pattern:
|
|
|
197
197
|
|
|
198
198
|
```ts
|
|
199
199
|
import { ref } from 'vue';
|
|
200
|
-
import type { DataTableSelectionKeyType } from '@hinen/pro-element-plus';
|
|
201
200
|
|
|
202
|
-
const
|
|
201
|
+
const selectedRows = ref<any[]>([]);
|
|
203
202
|
|
|
204
203
|
// Set selection programmatically
|
|
205
204
|
function selectAllVisible(rows: User[]) {
|
|
206
|
-
|
|
205
|
+
selectedRows.value = rows;
|
|
207
206
|
}
|
|
208
207
|
|
|
209
208
|
// Clear selection
|
|
210
209
|
function clearSelection() {
|
|
211
|
-
|
|
210
|
+
selectedRows.value = [];
|
|
212
211
|
}
|
|
213
212
|
|
|
214
213
|
// React to changes
|
|
215
|
-
watch(
|
|
216
|
-
console.log('Selected:',
|
|
214
|
+
watch(selectedRows, (rows) => {
|
|
215
|
+
console.log('Selected:', rows);
|
|
217
216
|
});
|
|
218
217
|
```
|
|
219
218
|
|
|
220
219
|
Recommended pattern:
|
|
221
220
|
|
|
222
|
-
- use `v-model:
|
|
221
|
+
- use `v-model:selectionRows` for controlled mode, no prop for internal mode
|
|
223
222
|
- always provide `rowKey` when selection should persist across pages
|
|
224
223
|
- update the model ref directly to change selection from parent
|
|
225
224
|
- use `selection` prop only for customization, never for state control
|
|
226
|
-
- instance methods like `getSelectionRows()` still work in controlled mode
|
|
225
|
+
- instance methods like `getSelectionRows()` and `setSelectionRows()` still work in controlled mode
|
|
226
|
+
- single-select mode returns an array with 0 or 1 element, multi-select returns 0..N elements
|
|
227
227
|
|
|
228
228
|
## 13. Cross-page selection with controlled mode
|
|
229
229
|
|
|
230
|
-
Use `v-model:
|
|
230
|
+
Use `v-model:selectionRows` with `rowKey` to maintain selection across pagination.
|
|
231
231
|
|
|
232
232
|
Minimal pattern:
|
|
233
233
|
|
|
234
234
|
```vue
|
|
235
235
|
<DataTable
|
|
236
|
-
v-model:
|
|
236
|
+
v-model:selectionRows="selectedRows"
|
|
237
237
|
:columns="columns"
|
|
238
238
|
:query-fn="queryFn"
|
|
239
239
|
row-key="id"
|
|
@@ -245,14 +245,17 @@ Minimal pattern:
|
|
|
245
245
|
```
|
|
246
246
|
|
|
247
247
|
```ts
|
|
248
|
-
const
|
|
248
|
+
const selectedRows = ref<any[]>([]);
|
|
249
249
|
|
|
250
250
|
// Select rows on page 1
|
|
251
|
-
|
|
251
|
+
selectedRows.value = [
|
|
252
|
+
{ id: 1, name: 'Alice' },
|
|
253
|
+
{ id: 2, name: 'Bob' },
|
|
254
|
+
{ id: 3, name: 'Charlie' },
|
|
255
|
+
];
|
|
252
256
|
|
|
253
257
|
// Navigate to page 2 and add more selections
|
|
254
|
-
|
|
255
|
-
selectedKeys.value = [...selectedKeys.value, 4, 5];
|
|
258
|
+
selectedRows.value = [...selectedRows.value, { id: 4, name: 'David' }, { id: 5, name: 'Eve' }];
|
|
256
259
|
|
|
257
260
|
// Built-in review UI shows all 5 selections
|
|
258
261
|
```
|
|
@@ -260,10 +263,33 @@ selectedKeys.value = [...selectedKeys.value, 4, 5];
|
|
|
260
263
|
Recommended pattern:
|
|
261
264
|
|
|
262
265
|
- `rowKey` is required for cross-page selection to work correctly
|
|
263
|
-
- the model accepts
|
|
266
|
+
- the model accepts full row objects from any page, not just the current one
|
|
264
267
|
- built-in review UI aggregates selections across pages when `rowKey` is provided
|
|
265
268
|
- `selectionChange` event emits all selected rows across pages
|
|
266
269
|
|
|
270
|
+
## 14. Non-controlled mode with initial selection
|
|
271
|
+
|
|
272
|
+
Use `initialSelectionRows` when the component should start with pre-selected rows but does not need parent-controlled selection.
|
|
273
|
+
|
|
274
|
+
Minimal pattern:
|
|
275
|
+
|
|
276
|
+
```vue
|
|
277
|
+
<DataTable
|
|
278
|
+
:initialSelectionRows="[{ id: 1, name: 'Alice' }]"
|
|
279
|
+
:columns="columns"
|
|
280
|
+
:query-fn="queryFn"
|
|
281
|
+
row-key="id"
|
|
282
|
+
:selection="{ mode: 'multiple' }"
|
|
283
|
+
/>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Recommended pattern:
|
|
287
|
+
|
|
288
|
+
- `rowKey` is required for cross-page selection to work correctly
|
|
289
|
+
- the component owns selection state after initialization
|
|
290
|
+
- use `selectionChange` to observe selection changes
|
|
291
|
+
- use `clearSelection()` instance method to clear selection programmatically
|
|
292
|
+
|
|
267
293
|
## 8. Sticky large-page table
|
|
268
294
|
|
|
269
295
|
Use `fixedHeader` or `fixedFooter` when the page is long enough that default table scrolling becomes awkward.
|
|
@@ -296,18 +322,18 @@ Typical fit:
|
|
|
296
322
|
|
|
297
323
|
## 10. Built-in radio single-select row
|
|
298
324
|
|
|
299
|
-
Use `selection.mode: 'single'` when the page wants `DataTable` to own a radio-based single-select row state.
|
|
325
|
+
Use `selection.mode: 'single'` with a `{ type: 'selection' }` column when the page wants `DataTable` to own a radio-based single-select row state.
|
|
300
326
|
|
|
301
327
|
Minimal pattern:
|
|
302
328
|
|
|
303
329
|
```vue
|
|
304
330
|
<DataTable
|
|
305
331
|
ref="tableRef"
|
|
306
|
-
:columns="columns"
|
|
332
|
+
:columns="[{ type: 'selection' }, ...columns]"
|
|
307
333
|
:data="rows"
|
|
308
334
|
row-key="id"
|
|
309
335
|
:selection="{ mode: 'single' }"
|
|
310
|
-
@
|
|
336
|
+
@selection-change="handleSelectionChange"
|
|
311
337
|
/>
|
|
312
338
|
```
|
|
313
339
|
|
|
@@ -315,32 +341,7 @@ Recommended pattern:
|
|
|
315
341
|
|
|
316
342
|
- provide `rowKey` when selection should stay stable across data updates
|
|
317
343
|
- treat the radio as the selection trigger
|
|
318
|
-
- use `
|
|
319
|
-
- use `
|
|
320
|
-
- use `getSelectedRow()` to read the currently selected row
|
|
321
|
-
|
|
322
|
-
Do not expect row clicks to change the current row in this mode.
|
|
323
|
-
|
|
324
|
-
## 11. Controlled current row with `currentRowKey`
|
|
325
|
-
|
|
326
|
-
Use `currentRowKey` when parent state should control which single-select row is active.
|
|
327
|
-
|
|
328
|
-
Minimal pattern:
|
|
329
|
-
|
|
330
|
-
```vue
|
|
331
|
-
<DataTable
|
|
332
|
-
:columns="columns"
|
|
333
|
-
:data="rows"
|
|
334
|
-
row-key="id"
|
|
335
|
-
:selection="{ mode: 'single' }"
|
|
336
|
-
:current-row-key="currentRowKey"
|
|
337
|
-
/>
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
Recommended pattern:
|
|
341
|
-
|
|
342
|
-
- always pair `currentRowKey` with `rowKey`
|
|
343
|
-
- set `currentRowKey` to a row key to select that row
|
|
344
|
-
- set `currentRowKey` to `undefined` to clear the current single-select row
|
|
345
|
-
|
|
346
|
-
Do not use `clearSelection()` for this flow; that targets checkbox selection rather than current-row state.
|
|
344
|
+
- use `setSelectionRows([row])` for imperative select
|
|
345
|
+
- use `setSelectionRows([])` to clear the single-select row
|
|
346
|
+
- use `getSelectedRow()` to read the currently selected row (returns first element or null)
|
|
347
|
+
- single-select mode returns an array with 0 or 1 element in `selectionChange`
|
|
@@ -49,10 +49,10 @@
|
|
|
49
49
|
They aggregate selection from all pages when cross-page selection is enabled.
|
|
50
50
|
|
|
51
51
|
- `selection.mode` controls selection behavior
|
|
52
|
-
Use `'single'` for radio column, `'multiple'` for checkbox column
|
|
52
|
+
Use `'single'` for radio column, `'multiple'` for checkbox column. Selection columns only appear when `{ type: 'selection' }` is in `columns`.
|
|
53
53
|
|
|
54
54
|
- `highlightCurrentRow` is a pure highlight switch
|
|
55
|
-
It
|
|
55
|
+
It controls native Element Plus row highlighting without affecting selection UI.
|
|
56
56
|
|
|
57
57
|
- `selection.mode: 'single'` renders a radio column
|
|
58
58
|
Clicking a radio selects that row and deselects any previously selected row.
|
|
@@ -60,67 +60,37 @@
|
|
|
60
60
|
- `selection.mode: 'multiple'` requires a selection column
|
|
61
61
|
You must include `{ type: 'selection' }` in `columns` for multi-select to work.
|
|
62
62
|
|
|
63
|
-
- `
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
- `columns` affects both display and query behavior
|
|
67
|
-
A column change can alter the table UI and the generated search form at the same time.
|
|
68
|
-
|
|
69
|
-
- `valueEnum` is not only visual
|
|
70
|
-
It can influence generated query controls as well as table display.
|
|
71
|
-
|
|
72
|
-
- Nested multi-level headers are not the primary target
|
|
73
|
-
If complex header composition is central to the feature, do not assume `DataTable` is the best fit.
|
|
74
|
-
|
|
75
|
-
- Do not overuse imperative control
|
|
76
|
-
`useDataTable()` should coordinate the component, not replace its internal state model.
|
|
77
|
-
|
|
78
|
-
- `highlightCurrentRow` is independent of selection mode
|
|
79
|
-
It controls native Element Plus row highlighting without affecting selection UI.
|
|
80
|
-
|
|
81
|
-
- Row click and current-row change are decoupled in single-select mode
|
|
82
|
-
With `selection.mode: 'single'`, clicking a row still emits `rowClick`, but only clicking the radio changes the current row.
|
|
83
|
-
|
|
84
|
-
- Controlled single-select requires `rowKey`
|
|
85
|
-
If you pass `currentRowKey` without `rowKey`, do not expect stable controlled current-row behavior.
|
|
86
|
-
|
|
87
|
-
- Clearing single-select current row uses `setCurrentRow()` or `clearSelection()`
|
|
88
|
-
Both methods clear the current radio-selected row. `setCurrentRow()` can also programmatically select a row.
|
|
89
|
-
|
|
90
|
-
- Empty `currentRowKey` clearing is a wrapper convention
|
|
91
|
-
`DataTable` treats `currentRowKey: undefined` as “clear current row” in single-select mode. This is aligned with the wrapper behavior, not a documented Element Plus `current-row-key` guarantee.
|
|
92
|
-
|
|
93
|
-
- An unmatched `currentRowKey` also clears the current single-select row
|
|
94
|
-
If the provided key does not resolve to any row in the current data set, `DataTable` clears the current row instead of preserving the previous one.
|
|
95
|
-
|
|
96
|
-
- Single-select behavior is unchanged
|
|
97
|
-
The built-in cross-page checkbox review does not alter `highlightCurrentRow`, radio selection, or current-row APIs.
|
|
98
|
-
|
|
99
|
-
- `v-model:selectedRowKeys` enables controlled selection mode
|
|
100
|
-
When this prop is provided, parent state owns selection. The component emits `update:selectedRowKeys` but defers to the prop value.
|
|
63
|
+
- `v-model:selectionRows` enables controlled selection mode
|
|
64
|
+
When this prop is provided, parent state owns selection. The component emits `update:selectionRows` but defers to the prop value.
|
|
101
65
|
|
|
102
66
|
- Controlled mode vs internal mode
|
|
103
67
|
Internal mode: component owns selection state, use `clearSelection()` and `getSelectionRows()`.
|
|
104
|
-
Controlled mode: parent owns state via `
|
|
68
|
+
Controlled mode: parent owns state via `selectionRows`, update the model ref directly to change selection.
|
|
69
|
+
|
|
70
|
+
- `initialSelectionRows` provides initial selection for non-controlled mode
|
|
71
|
+
Use this when the component should start pre-selected but does not need parent control.
|
|
105
72
|
|
|
106
73
|
- `selection` prop is for customization only
|
|
107
|
-
Never use `selection` to control selection state. Use `v-model:
|
|
74
|
+
Never use `selection` to control selection state. Use `v-model:selectionRows` for state control.
|
|
108
75
|
`formatter` and `render` in `selection` only customize the review item display.
|
|
109
76
|
|
|
110
|
-
- `
|
|
111
|
-
Without `rowKey`, the component cannot identify which rows correspond to the provided
|
|
77
|
+
- `selectionRows` requires matching `rowKey` for cross-page selection
|
|
78
|
+
Without `rowKey`, the component cannot identify which rows correspond to the provided objects across pages.
|
|
112
79
|
|
|
113
|
-
- `
|
|
114
|
-
In controlled mode with `rowKey`, the model can contain
|
|
80
|
+
- `selectionRows` accepts full row objects from any page
|
|
81
|
+
In controlled mode with `rowKey`, the model can contain rows from pages other than the current one. The built-in review UI aggregates them.
|
|
115
82
|
|
|
116
83
|
- `selectionChange` returns all selected rows across pages
|
|
117
84
|
In both controlled and internal modes, the event emits the aggregated selection from all pages.
|
|
118
85
|
|
|
119
86
|
- Instance methods still work in controlled mode
|
|
120
|
-
`getSelectionRows()`, `toggleRowSelection()`, etc. continue to function, but parent state should be the primary control mechanism.
|
|
87
|
+
`getSelectionRows()`, `setSelectionRows()`, `toggleRowSelection()`, etc. continue to function, but parent state should be the primary control mechanism.
|
|
121
88
|
|
|
122
89
|
- Clearing selection in controlled mode
|
|
123
|
-
Call `clearSelection()` or set `
|
|
90
|
+
Call `clearSelection()` or set `selectedRows.value = []`. In controlled mode, prefer updating the model directly.
|
|
91
|
+
|
|
92
|
+
- Single-select mode returns array with 0 or 1 element
|
|
93
|
+
Multi-select mode returns 0..N elements. Both use the same `selectionRows` API.
|
|
124
94
|
|
|
125
95
|
- Default placement for review popover is 'top-start'
|
|
126
96
|
When using `selectionBar.reviewPopoverProps`, the default placement is 'top-start'. Only override if necessary.
|
|
@@ -169,29 +169,29 @@ The built-in checkbox review keeps cross-page state internally only when `rowKey
|
|
|
169
169
|
- `reviewPopoverProps` customizes the built-in 查看已选 popover
|
|
170
170
|
- use the `selectionBar` slot only when the page should replace the built-in review UI entirely
|
|
171
171
|
|
|
172
|
-
### `
|
|
172
|
+
### `selectionRows` / `v-model:selectionRows`
|
|
173
173
|
|
|
174
174
|
Controls selection state from parent (controlled mode).
|
|
175
175
|
|
|
176
|
-
Type: `
|
|
176
|
+
Type: `any[]` (array of full row objects)
|
|
177
177
|
|
|
178
178
|
Use this when:
|
|
179
179
|
|
|
180
|
-
- parent needs reactive access to selected row
|
|
180
|
+
- parent needs reactive access to selected row objects
|
|
181
181
|
- selection should sync with external state (URL, storage, other components)
|
|
182
182
|
- programmatic selection control is required
|
|
183
183
|
|
|
184
184
|
When provided, `DataTable` operates in controlled mode:
|
|
185
185
|
|
|
186
|
-
- the component emits `update:
|
|
186
|
+
- the component emits `update:selectionRows` on selection changes
|
|
187
187
|
- parent state becomes the source of truth
|
|
188
188
|
- internal selection state defers to the prop
|
|
189
189
|
|
|
190
|
-
Cross-page selection works with `
|
|
190
|
+
Cross-page selection works with `selectionRows` when `rowKey` is defined. The prop accepts full row objects from any page.
|
|
191
191
|
|
|
192
192
|
```vue
|
|
193
193
|
<DataTable
|
|
194
|
-
v-model:
|
|
194
|
+
v-model:selectionRows="selectedRows"
|
|
195
195
|
:columns="columns"
|
|
196
196
|
:query-fn="queryFn"
|
|
197
197
|
row-key="id"
|
|
@@ -200,13 +200,30 @@ Cross-page selection works with `selectedRowKeys` when `rowKey` is defined. The
|
|
|
200
200
|
```
|
|
201
201
|
|
|
202
202
|
```ts
|
|
203
|
-
const
|
|
203
|
+
const selectedRows = ref<any[]>([]);
|
|
204
204
|
|
|
205
205
|
// Set programmatically
|
|
206
|
-
|
|
206
|
+
selectedRows.value = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
|
|
207
207
|
|
|
208
208
|
// Clear
|
|
209
|
-
|
|
209
|
+
selectedRows.value = [];
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### `initialSelectionRows`
|
|
213
|
+
|
|
214
|
+
Initial selected rows for non-controlled mode.
|
|
215
|
+
|
|
216
|
+
Type: `any[]` (array of full row objects)
|
|
217
|
+
|
|
218
|
+
Use this when the component should start with pre-selected rows but does not need parent-controlled selection.
|
|
219
|
+
|
|
220
|
+
```vue
|
|
221
|
+
<DataTable
|
|
222
|
+
:initialSelectionRows="[{ id: 1, name: 'Alice' }]"
|
|
223
|
+
:columns="columns"
|
|
224
|
+
:query-fn="queryFn"
|
|
225
|
+
row-key="id"
|
|
226
|
+
/>
|
|
210
227
|
```
|
|
211
228
|
|
|
212
229
|
### `selection`
|
|
@@ -260,10 +277,10 @@ Controls selection behavior and customization.
|
|
|
260
277
|
|
|
261
278
|
Common fields:
|
|
262
279
|
|
|
263
|
-
- `mode` — `'single'` | `'multiple'`
|
|
280
|
+
- `mode` — `'single'` | `'multiple'` (default `'multiple'`)
|
|
264
281
|
- `'single'` renders a leading radio column for single-select with cross-page support
|
|
265
282
|
- `'multiple'` requires a `{ type: 'selection' }` column for multi-select with cross-page support
|
|
266
|
-
-
|
|
283
|
+
- if no selection column is provided, selection UI is hidden
|
|
267
284
|
- `formatter(row)` customizes the default review tag text
|
|
268
285
|
- `render(...)` customizes each built-in review item
|
|
269
286
|
|
|
@@ -271,13 +288,13 @@ Use `rowKey` with this when selection review should stay correct across pages.
|
|
|
271
288
|
|
|
272
289
|
```vue
|
|
273
290
|
<!-- Single select with radio column -->
|
|
274
|
-
<DataTable :selection="{ mode: 'single' }" :columns="columns" />
|
|
291
|
+
<DataTable :selection="{ mode: 'single' }" :columns="[{ type: 'selection' }, ...columns]" />
|
|
275
292
|
|
|
276
293
|
<!-- Multi select with checkbox column -->
|
|
277
294
|
<DataTable :selection="{ mode: 'multiple' }" :columns="[{ type: 'selection' }, ...columns]" />
|
|
278
295
|
|
|
279
|
-
<!--
|
|
280
|
-
<DataTable :
|
|
296
|
+
<!-- No selection column -->
|
|
297
|
+
<DataTable :columns="columns" />
|
|
281
298
|
```
|
|
282
299
|
|
|
283
300
|
### `rowKey`
|
|
@@ -348,9 +365,11 @@ Current-row related methods:
|
|
|
348
365
|
|
|
349
366
|
Selection notes:
|
|
350
367
|
|
|
351
|
-
- `getSelectionRows()` returns all selected rows across pages (
|
|
352
|
-
- `
|
|
353
|
-
-
|
|
368
|
+
- `getSelectionRows()` returns all selected rows across pages (full row objects)
|
|
369
|
+
- `setSelectionRows(rows)` sets selected rows programmatically (accepts full row objects)
|
|
370
|
+
- `selectionChange` emits all selected rows across pages (full row objects)
|
|
371
|
+
- single-select mode returns an array with 0 or 1 element, multi-select returns 0..N elements
|
|
372
|
+
- cross-page selection state is internal unless `v-model:selectionRows` is provided
|
|
354
373
|
|
|
355
374
|
Notes:
|
|
356
375
|
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@charset "UTF-8";.pel-ellipsis-text.is-truncated[data-v-36b1aefb]{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.pel-ellipsis-text.line-clamp[data-v-36b1aefb]{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;display:box;-webkit-line-clamp:var(--7a7a879f);line-clamp:var(--7a7a879f)}.pel-form-item-ghost{position:relative;margin-bottom:18px}.pel-form-item-ghost>.el-form-item{margin-bottom:0}.pel-form-item-ghost>.el-form-item>.el-form-item__content{position:unset}.pel-form-item-label-with-tooltip{display:inline-flex;align-items:center;gap:4px}.pel-form-item-error-wrap{position:absolute;top:100%;left:0;width:100%;min-height:20px;padding-top:2px;display:flex;align-items:flex-start;z-index:10;pointer-events:none}.pel-form-item-error-content{pointer-events:auto;color:var(--el-color-danger);font-size:12px;line-height:1.2;width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:all .2s cubic-bezier(.4,0,.2,1);border-radius:4px;cursor:default}.pel-form-item-error-content.is-truncated{cursor:help}.pel-form-item-error-content.is-truncated:hover{position:absolute;top:2px;left:0;width:auto;max-width:100%;min-width:100%;background-color:var(--el-color-danger);color:#fff;white-space:normal;overflow:visible;padding:6px 8px;transform:translateY(-4px);box-shadow:0 4px 12px #00000026;z-index:100;animation:error-expand .2s ease forwards}@keyframes error-expand{0%{opacity:.8;transform:translateY(0) scale(.98)}to{opacity:1;transform:translateY(-4px) scale(1)}}.pel-query-form{display:flex;align-items:flex-start;gap:80px}.pel-query-form-items{display:flex;flex-wrap:wrap;flex-grow:1}.pel-query-form-item-wrapper .el-input-number,.pel-query-form-item-wrapper .el-cascader{width:100%}.pel-query-form-item-wrapper .el-date-editor{--el-date-editor-width: 100%}.pel-query-form-item-wrapper .el-form-item__error{width:100%}.pel-query-form-buttons{flex-shrink:0}.pel-query-form-buttons.el-form-item--label-right .el-form-item__label-wrap,.pel-query-form-buttons.el-form-item--label-left .el-form-item__label-wrap{display:none}.pel-query-form-buttons .el-form-item__label{visibility:hidden}.pel-query-form-hide-label .el-form-item .el-form-item__label{display:none}.pel-query-form-collapse-button{margin-right:8px}.pel-query-form-collapse-icon{margin-left:4px;transition:transform .3s ease-in-out}.pel-query-form-collapsed .pel-query-form-collapse-icon{transform:rotate(180deg)}.pel-query-form-tags{margin-bottom:10px}.pel-query-form-tags.el-form--inline .el-form-item{margin-right:8px;margin-bottom:8px}.pel-query-form-item-tag{padding:0 8px;background-color:var(--el-fill-color);border-radius:4px;border:1px solid transparent}.pel-query-form-item-tag.is-error{border-color:var(--el-color-danger)}.pel-query-form-item-tag .error-icon{margin-left:4px;color:var(--el-color-danger)}.pel-query-form-item-tag .el-form-item__label{padding-right:4px}.pel-query-form-item-tag .el-form-item__label:after{content:":"}.pel-query-form-item-tag-content{max-width:250px}.pel-query-form-item-tag .el-form-item__content{color:var(--el-text-color-regular)}.pel-query-form-item-tag .close-btn.is-text{margin-left:4px;width:18px;height:18px;border-radius:4px;background-color:var(--el-fill-color-darker)}.pel-query-form-item-tag .close-btn.is-text:hover{background-color:#fff}.pel-data-table
|
|
1
|
+
@charset "UTF-8";.pel-ellipsis-text.is-truncated[data-v-36b1aefb]{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.pel-ellipsis-text.line-clamp[data-v-36b1aefb]{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;display:box;-webkit-line-clamp:var(--7a7a879f);line-clamp:var(--7a7a879f)}.pel-form-item-ghost{position:relative;margin-bottom:18px}.pel-form-item-ghost>.el-form-item{margin-bottom:0}.pel-form-item-ghost>.el-form-item>.el-form-item__content{position:unset}.pel-form-item-label-with-tooltip{display:inline-flex;align-items:center;gap:4px}.pel-form-item-error-wrap{position:absolute;top:100%;left:0;width:100%;min-height:20px;padding-top:2px;display:flex;align-items:flex-start;z-index:10;pointer-events:none}.pel-form-item-error-content{pointer-events:auto;color:var(--el-color-danger);font-size:12px;line-height:1.2;width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:all .2s cubic-bezier(.4,0,.2,1);border-radius:4px;cursor:default}.pel-form-item-error-content.is-truncated{cursor:help}.pel-form-item-error-content.is-truncated:hover{position:absolute;top:2px;left:0;width:auto;max-width:100%;min-width:100%;background-color:var(--el-color-danger);color:#fff;white-space:normal;overflow:visible;padding:6px 8px;transform:translateY(-4px);box-shadow:0 4px 12px #00000026;z-index:100;animation:error-expand .2s ease forwards}@keyframes error-expand{0%{opacity:.8;transform:translateY(0) scale(.98)}to{opacity:1;transform:translateY(-4px) scale(1)}}.pel-query-form{display:flex;align-items:flex-start;gap:80px}.pel-query-form-items{display:flex;flex-wrap:wrap;flex-grow:1}.pel-query-form-item-wrapper .el-input-number,.pel-query-form-item-wrapper .el-cascader{width:100%}.pel-query-form-item-wrapper .el-date-editor{--el-date-editor-width: 100%}.pel-query-form-item-wrapper .el-form-item__error{width:100%}.pel-query-form-buttons{flex-shrink:0}.pel-query-form-buttons.el-form-item--label-right .el-form-item__label-wrap,.pel-query-form-buttons.el-form-item--label-left .el-form-item__label-wrap{display:none}.pel-query-form-buttons .el-form-item__label{visibility:hidden}.pel-query-form-hide-label .el-form-item .el-form-item__label{display:none}.pel-query-form-collapse-button{margin-right:8px}.pel-query-form-collapse-icon{margin-left:4px;transition:transform .3s ease-in-out}.pel-query-form-collapsed .pel-query-form-collapse-icon{transform:rotate(180deg)}.pel-query-form-tags{margin-bottom:10px}.pel-query-form-tags.el-form--inline .el-form-item{margin-right:8px;margin-bottom:8px}.pel-query-form-item-tag{padding:0 8px;background-color:var(--el-fill-color);border-radius:4px;border:1px solid transparent}.pel-query-form-item-tag.is-error{border-color:var(--el-color-danger)}.pel-query-form-item-tag .error-icon{margin-left:4px;color:var(--el-color-danger)}.pel-query-form-item-tag .el-form-item__label{padding-right:4px}.pel-query-form-item-tag .el-form-item__label:after{content:":"}.pel-query-form-item-tag-content{max-width:250px}.pel-query-form-item-tag .el-form-item__content{color:var(--el-text-color-regular)}.pel-query-form-item-tag .close-btn.is-text{margin-left:4px;width:18px;height:18px;border-radius:4px;background-color:var(--el-fill-color-darker)}.pel-query-form-item-tag .close-btn.is-text:hover{background-color:#fff}.pel-data-table-selection-bar{display:flex;align-items:center;gap:8px;margin-bottom:16px;padding:12px 16px;color:var(--el-table-text-color);font-size:var(--el-font-size-base);border-radius:4px;background-color:var(--el-fill-color)}.pel-data-table-selection-bar>.el-button{margin-left:0}.pel-data-table-selection-bar-popper.el-popper{padding:0}.pel-data-table-selection-bar-popover-content{display:flex;flex-wrap:wrap;gap:8px;padding:16px}.pel-data-table-selection-bar-tag{display:inline-flex;overflow:hidden}.pel-data-table-selection-bar-tag .el-tag__content{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;flex:1}.pel-data-table{display:flex;flex-direction:column}.pel-data-table-toolbar{margin-bottom:16px}.pel-data-table-footer-wrapper{display:flex;align-items:center;justify-content:flex-end;gap:16px;flex-wrap:wrap;width:100%;background:#fff}.pel-data-table-footer-wrapper--with-footer{justify-content:space-between}.pel-data-table-footer{display:flex;align-items:center;flex:1;min-width:0;padding:16px 0;background:#fff;color:var(--el-text-color-regular);font-size:var(--el-font-size-base);line-height:var(--el-line-height-base)}.pel-data-table .el-affix--fixed .pel-data-table-footer-wrapper{border-top:1px solid var(--el-border-color-lighter)}.pel-data-table-pagination{justify-content:flex-end;padding:16px 0;background:#fff}.pel-data-table .el-table{--el-table-header-bg-color: var(--el-fill-color);scroll-margin-top:calc(var(--3bfc4308) * 1px)}.pel-data-table .el-table .cell:not(.el-tooltip){text-overflow:unset}.pel-data-table .el-table th.el-table__cell{padding-top:10px;padding-bottom:10px}.pel-data-table .el-table__header-wrapper{z-index:5}.pel-data-table .el-table .el-scrollbar__bar.is-horizontal.fixed{position:fixed;bottom:calc(var(--425bea2e) + var(--4e5abd9a));left:unset;right:unset}.pel-data-table-cell-tooltip{max-width:300px}.el-dialog{--el-dialog-border-radius: 12px !important;--el-dialog-padding-primary: 32px !important;--el-dialog-padding-x: 32px;--el-dialog-padding-y: 20px;--el-dialog-margin-top: 8vh !important;--el-dialog-width: 95%;display:flex;flex-direction:column;padding:0}.el-dialog__scrollbar{padding-left:32px;padding-right:32px}.el-dialog__small{max-width:450px}.el-dialog__large{max-width:960px}.el-dialog__default{max-width:680px}.el-dialog:not(.is-align-center){max-height:calc(100vh - var(--el-dialog-margin-top) - 50px)}.el-dialog.is-align-center{max-height:calc(100vh - 100px)}.el-dialog__header{z-index:2;flex-shrink:0;padding-top:var(--el-dialog-padding-y);padding-left:var(--el-dialog-padding-x);padding-bottom:var(--el-dialog-padding-y)}.el-dialog__header-shadow{box-shadow:0 0 6px #0000001a}.el-dialog__footer{flex-shrink:0;padding-top:var(--el-dialog-padding-y);padding-bottom:var(--el-dialog-padding-y);padding-left:var(--el-dialog-padding-x);padding-right:var(--el-dialog-padding-x)}.el-dialog__footer-shadow{box-shadow:0 -1px 6px #0000001a}.el-dialog__body{flex-grow:1;padding-left:0;padding-right:0;overflow:hidden;display:flex;flex-direction:column}.el-dialog__body .el-scrollbar{flex-grow:1;display:flex;flex-direction:column;overflow:hidden}.el-dialog__headerbtn{top:12px;right:15px}.pel-image-error{display:flex;flex-direction:column;gap:8px}.pel-image-refresh-button{display:flex;align-items:center;justify-content:center;font-size:24px;cursor:pointer}.pel-image .el-loading-spinner{margin-top:0;transform:translateY(-50%)}.pel-image-placeholder{display:flex;align-items:center;justify-content:center;width:100%;height:100%;background-color:var(--el-fill-color-light)}.pel-image-placeholder-loading{color:var(--el-text-color-placeholder)}.pel-image-empty{position:relative;background-color:var(--el-fill-color-light)}.pel-image-empty-icon{position:absolute;display:flex;align-items:center;justify-content:center;width:100%;height:100%;font-size:24px;color:var(--el-text-color-placeholder)}.el-drawer{--el-drawer-border-radius: 12px;--el-drawer-padding-x: 32px;--el-drawer-padding-y: 20px;display:flex;flex-direction:column;padding:0}.el-drawer__rtl{border-top-left-radius:var(--el-drawer-border-radius);border-bottom-left-radius:var(--el-drawer-border-radius)}.el-drawer__ltr{border-top-right-radius:var(--el-drawer-border-radius);border-bottom-right-radius:var(--el-drawer-border-radius)}.el-drawer__ttb{border-bottom-left-radius:var(--el-drawer-border-radius);border-bottom-right-radius:var(--el-drawer-border-radius)}.el-drawer__btt{border-top-left-radius:var(--el-drawer-border-radius);border-top-right-radius:var(--el-drawer-border-radius)}.el-drawer__scrollbar{padding-left:var(--el-drawer-padding-x);padding-right:var(--el-drawer-padding-x)}.el-drawer__rtl.el-drawer__small,.el-drawer__ltr.el-drawer__small{max-width:380px}.el-drawer__rtl.el-drawer__large,.el-drawer__ltr.el-drawer__large{max-width:680px}.el-drawer__rtl.el-drawer__default,.el-drawer__ltr.el-drawer__default{max-width:450px}.el-drawer__ttb.el-drawer__small,.el-drawer__btt.el-drawer__small{max-height:380px}.el-drawer__ttb.el-drawer__large,.el-drawer__btt.el-drawer__large{max-height:680px}.el-drawer__ttb.el-drawer__default,.el-drawer__btt.el-drawer__default{max-height:450px}.el-drawer__header{z-index:2;flex-shrink:0;padding-top:var(--el-drawer-padding-y);padding-bottom:var(--el-drawer-padding-y);padding-left:var(--el-drawer-padding-x);padding-right:var(--el-drawer-padding-y);margin-bottom:0}.el-drawer__header-shadow{box-shadow:0 2px 12px #0000001a}.el-drawer__footer{flex-shrink:0;padding-top:var(--el-drawer-padding-y);padding-bottom:var(--el-drawer-padding-y);padding-left:var(--el-drawer-padding-x);padding-right:var(--el-drawer-padding-y)}.el-drawer__footer-shadow{box-shadow:0 -1px 6px #0000001a}.el-drawer__body{display:flex;flex-grow:1;flex-direction:column;padding:0;overflow:hidden}.el-drawer__body .el-scrollbar{flex-grow:1;flex-direction:column;display:flex;overflow:hidden}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.test.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/DataTable.test.ts"],"names":[],"mappings":""}
|