vgapp 1.4.7 → 1.4.9
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/README.md +24 -2
- package/app/modules/base-module.js +14 -2
- package/app/modules/module-fn.js +5 -4
- package/app/modules/vgalert/js/vgalert.js +21 -1
- package/app/modules/vgalert/scss/vgalert.scss +48 -0
- package/app/modules/vgdropdown/js/vgdropdown.js +58 -27
- package/app/modules/vgfilepreview/js/renderers/video-modal.js +5 -1
- package/app/modules/vgfilepreview/js/renderers/video.js +6 -1
- package/app/modules/vgfilepreview/js/vgfilepreview.js +5 -1
- package/app/modules/vgfiles/js/base.js +14 -5
- package/app/modules/vgfiles/js/droppable.js +37 -31
- package/app/modules/vgfiles/js/vgfiles.js +5 -2
- package/app/modules/vgfiles/scss/_variables.scss +3 -1
- package/app/modules/vgfiles/scss/vgfiles.scss +55 -10
- package/app/modules/vgformsender/js/vgformsender.js +5 -2
- package/app/modules/vgloadmore/js/vgloadmore.js +35 -7
- package/app/modules/vgnestable/js/vgnestable.js +140 -0
- package/app/modules/vgnestable/scss/_variables.scss +16 -9
- package/app/modules/vgnestable/scss/vgnestable.scss +35 -2
- package/app/modules/vgtable/index.js +3 -0
- package/app/modules/vgtable/js/_columns.js +567 -0
- package/app/modules/vgtable/js/_expandable.js +242 -0
- package/app/modules/vgtable/js/_filters.js +264 -0
- package/app/modules/vgtable/js/_fixed-columns.js +249 -0
- package/app/modules/vgtable/js/_i18n.js +75 -0
- package/app/modules/vgtable/js/_options.js +428 -0
- package/app/modules/vgtable/js/_pagination.js +491 -0
- package/app/modules/vgtable/js/_panning.js +124 -0
- package/app/modules/vgtable/js/_params-groups.js +21 -0
- package/app/modules/vgtable/js/_remote.js +395 -0
- package/app/modules/vgtable/js/_row-reorder.js +268 -0
- package/app/modules/vgtable/js/_search.js +134 -0
- package/app/modules/vgtable/js/_selection.js +113 -0
- package/app/modules/vgtable/js/_skeleton.js +123 -0
- package/app/modules/vgtable/js/_sorting.js +340 -0
- package/app/modules/vgtable/js/_states.js +143 -0
- package/app/modules/vgtable/js/_sticky-header.js +193 -0
- package/app/modules/vgtable/js/_url-state.js +178 -0
- package/app/modules/vgtable/js/vgtable.js +1444 -0
- package/app/modules/vgtable/readme.md +922 -0
- package/app/modules/vgtable/scss/_columns.scss +52 -0
- package/app/modules/vgtable/scss/_expandable.scss +54 -0
- package/app/modules/vgtable/scss/_fixed-columns.scss +117 -0
- package/app/modules/vgtable/scss/_pagination.scss +191 -0
- package/app/modules/vgtable/scss/_row-reorder.scss +45 -0
- package/app/modules/vgtable/scss/_skeleton.scss +65 -0
- package/app/modules/vgtable/scss/_sorting.scss +89 -0
- package/app/modules/vgtable/scss/_states.scss +70 -0
- package/app/modules/vgtable/scss/_sticky-header.scss +121 -0
- package/app/modules/vgtable/scss/_variables.scss +296 -0
- package/app/modules/vgtable/scss/vgtable.scss +206 -0
- package/app/utils/js/components/placement.js +64 -10
- package/app/vgapp.js +3 -3
- package/build/vgapp.css +1 -1
- package/build/vgapp.css.map +1 -1
- package/build/vgapp.js +1 -1
- package/build/vgapp.js.map +1 -1
- package/index.js +1 -1
- package/index.scss +3 -3
- package/package.json +5 -5
- package/app/modules/vgdynamictable/index.js +0 -4
- package/app/modules/vgdynamictable/js/editable.js +0 -438
- package/app/modules/vgdynamictable/js/expandable.js +0 -248
- package/app/modules/vgdynamictable/js/filters.js +0 -450
- package/app/modules/vgdynamictable/js/fixed.js +0 -566
- package/app/modules/vgdynamictable/js/options.js +0 -650
- package/app/modules/vgdynamictable/js/pagination.js +0 -623
- package/app/modules/vgdynamictable/js/search.js +0 -82
- package/app/modules/vgdynamictable/js/skeleton.js +0 -144
- package/app/modules/vgdynamictable/js/sortable.js +0 -442
- package/app/modules/vgdynamictable/js/summary-footer.js +0 -284
- package/app/modules/vgdynamictable/js/table-remote.js +0 -821
- package/app/modules/vgdynamictable/js/table-state.js +0 -243
- package/app/modules/vgdynamictable/js/table-url-state.js +0 -444
- package/app/modules/vgdynamictable/js/utils/common.js +0 -48
- package/app/modules/vgdynamictable/js/vgdynamictable.js +0 -3870
- package/app/modules/vgdynamictable/js/viewport.js +0 -322
- package/app/modules/vgdynamictable/readme.md +0 -251
- package/app/modules/vgdynamictable/scss/_actions.scss +0 -196
- package/app/modules/vgdynamictable/scss/_pagination.scss +0 -186
- package/app/modules/vgdynamictable/scss/_skeleton.scss +0 -63
- package/app/modules/vgdynamictable/scss/_sortable.scss +0 -66
- package/app/modules/vgdynamictable/scss/_table.scss +0 -137
- package/app/modules/vgdynamictable/scss/_variables.scss +0 -138
- package/app/modules/vgdynamictable/scss/vgdynamictable.scss +0 -264
|
@@ -0,0 +1,922 @@
|
|
|
1
|
+
# VGTable
|
|
2
|
+
|
|
3
|
+
`VGTable` — базовый модуль таблиц VGApp. Компонент работает с обычной HTML-таблицей, не заменяет её собственной моделью данных и добавляет интерактивность только для включённых возможностей.
|
|
4
|
+
|
|
5
|
+
## Возможности
|
|
6
|
+
|
|
7
|
+
- локальная и серверная сортировка, включая мультисортировку;
|
|
8
|
+
- локальная и Remote-пагинация;
|
|
9
|
+
- поиск, фильтры и синхронизация состояния с URL;
|
|
10
|
+
- состояния `empty`, `filtered-empty`, `error`, повтор запроса и сброс фильтров;
|
|
11
|
+
- фиксированный заголовок при прокрутке контейнера или страницы;
|
|
12
|
+
- фиксированные и последовательно складывающиеся колонки;
|
|
13
|
+
- изменение ширины, перестановка, скрытие и отображение колонок;
|
|
14
|
+
- самостоятельная перестановка строк;
|
|
15
|
+
- выбор строк и многоуровневые раскрываемые строки;
|
|
16
|
+
- Remote-режим с JSON-данными или готовой серверной разметкой строк;
|
|
17
|
+
- skeleton загрузки без схлопывания таблицы;
|
|
18
|
+
- встроенные локали `ru` и `en`, пользовательские словари;
|
|
19
|
+
- сохранение пользовательских настроек в `localStorage`;
|
|
20
|
+
- управление через Data API, JavaScript API и DOM-события.
|
|
21
|
+
|
|
22
|
+
## Подключение
|
|
23
|
+
|
|
24
|
+
Модуль экспортируется из основной точки входа пакета:
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import {VGTable} from 'vgapp';
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Стили подключаются общей SCSS-точкой входа VGApp.
|
|
31
|
+
|
|
32
|
+
## Разметка
|
|
33
|
+
|
|
34
|
+
Рекомендуется явно использовать два контейнера:
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<div class="vg-table-wrapper">
|
|
38
|
+
<div class="vg-table-container">
|
|
39
|
+
<table class="vg-table" data-vg-table>
|
|
40
|
+
<thead>
|
|
41
|
+
<tr>
|
|
42
|
+
<th data-field="id" data-sort-type="number">ID</th>
|
|
43
|
+
<th data-field="name">Название</th>
|
|
44
|
+
<th data-field="status">Статус</th>
|
|
45
|
+
</tr>
|
|
46
|
+
</thead>
|
|
47
|
+
<tbody>
|
|
48
|
+
<tr data-row-key="1">
|
|
49
|
+
<td>1</td>
|
|
50
|
+
<td>Первая запись</td>
|
|
51
|
+
<td>Активна</td>
|
|
52
|
+
</tr>
|
|
53
|
+
</tbody>
|
|
54
|
+
</table>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Назначение элементов:
|
|
60
|
+
|
|
61
|
+
- `.vg-table-wrapper` — внешний контейнер таблицы и панелей управления;
|
|
62
|
+
- `.vg-table-container` — внутренняя область прокрутки непосредственно таблицы;
|
|
63
|
+
- `.vg-table` — сама таблица;
|
|
64
|
+
- `data-vg-table` — маркер автоматической инициализации;
|
|
65
|
+
- `data-field` — стабильный идентификатор колонки для сортировки, Remote-данных и управления колонками;
|
|
66
|
+
- `data-row-key` — стабильный идентификатор строки для перестановки и связанных сценариев.
|
|
67
|
+
|
|
68
|
+
Если wrapper или container отсутствуют, компонент создаст недостающую обёртку самостоятельно и корректно удалит её при `dispose()`. Явная разметка предпочтительна: она заранее разделяет прокрутку таблицы и внешнюю пагинацию.
|
|
69
|
+
|
|
70
|
+
## Инициализация
|
|
71
|
+
|
|
72
|
+
### Автоматическая
|
|
73
|
+
|
|
74
|
+
Все элементы с `data-vg-table` инициализируются после `DOMContentLoaded`:
|
|
75
|
+
|
|
76
|
+
```html
|
|
77
|
+
<table class="vg-table" data-vg-table>
|
|
78
|
+
<!-- ... -->
|
|
79
|
+
</table>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Через JavaScript
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
const element = document.querySelector('#orders-table');
|
|
86
|
+
const table = VGTable.getOrCreateInstance(element, {
|
|
87
|
+
pagination: {
|
|
88
|
+
enabled: true,
|
|
89
|
+
per: 10,
|
|
90
|
+
size: {
|
|
91
|
+
enabled: true,
|
|
92
|
+
options: [10, 25, 50, 100],
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
table.init();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Повторный вызов `getOrCreateInstance()` возвращает существующий экземпляр.
|
|
101
|
+
|
|
102
|
+
## Data API
|
|
103
|
+
|
|
104
|
+
Основные возможности можно включить атрибутами таблицы:
|
|
105
|
+
|
|
106
|
+
```html
|
|
107
|
+
<table
|
|
108
|
+
id="orders-table"
|
|
109
|
+
class="vg-table"
|
|
110
|
+
data-vg-table
|
|
111
|
+
data-locale="ru"
|
|
112
|
+
data-pagination-enabled="true"
|
|
113
|
+
data-pagination-per-page="10"
|
|
114
|
+
data-pagination-show-per-page="true"
|
|
115
|
+
data-pagination-per-page-options="10,25,50,100"
|
|
116
|
+
data-sort-multiple="true"
|
|
117
|
+
data-sticky-header-enabled="true"
|
|
118
|
+
data-sticky-header-mode="container"
|
|
119
|
+
data-sticky-header-max-height="32rem"
|
|
120
|
+
>
|
|
121
|
+
<!-- ... -->
|
|
122
|
+
</table>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Имена атрибутов обычно повторяют группы JavaScript-настроек: например, `stickyHeader.maxHeight` соответствует `data-sticky-header-max-height`. Для совместимости с VGDynamicTable некоторые параметры также имеют короткие aliases, например `data-pagination-show-per-page`.
|
|
126
|
+
|
|
127
|
+
Полный актуальный список параметров, допустимых значений и соответствующих data-атрибутов находится в `js/_options.js`.
|
|
128
|
+
|
|
129
|
+
## Настройки
|
|
130
|
+
|
|
131
|
+
Ниже приведена структура основных параметров. Неуказанные значения дополняются настройками по умолчанию.
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
const table = new VGTable(element, {
|
|
135
|
+
locale: 'ru',
|
|
136
|
+
i18n: {},
|
|
137
|
+
|
|
138
|
+
sort: {
|
|
139
|
+
enabled: true,
|
|
140
|
+
hover: true,
|
|
141
|
+
multiple: false,
|
|
142
|
+
multipleWithShift: true,
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
pan: {
|
|
146
|
+
enabled: true,
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
pagination: {
|
|
150
|
+
enabled: false,
|
|
151
|
+
page: 1,
|
|
152
|
+
per: 10,
|
|
153
|
+
max: 100,
|
|
154
|
+
position: 'bottom', // top | bottom | both
|
|
155
|
+
align: 'right', // left | center | right | between
|
|
156
|
+
ellipsis: true,
|
|
157
|
+
ellipsisHover: true,
|
|
158
|
+
threshold: 5,
|
|
159
|
+
visible: 5,
|
|
160
|
+
size: {
|
|
161
|
+
enabled: false,
|
|
162
|
+
options: [10, 25, 50, 100],
|
|
163
|
+
label: 'Строк на странице',
|
|
164
|
+
suffix: 'на страницу',
|
|
165
|
+
},
|
|
166
|
+
quick: {
|
|
167
|
+
enabled: false, // true | false | auto
|
|
168
|
+
label: 'Перейти к странице',
|
|
169
|
+
button: 'Перейти',
|
|
170
|
+
},
|
|
171
|
+
persist: {
|
|
172
|
+
page: true,
|
|
173
|
+
per: true,
|
|
174
|
+
},
|
|
175
|
+
storage: {
|
|
176
|
+
key: '',
|
|
177
|
+
},
|
|
178
|
+
scroll: false, // false | table | window
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
stickyHeader: {
|
|
182
|
+
enabled: false,
|
|
183
|
+
mode: 'container', // container | page
|
|
184
|
+
top: null,
|
|
185
|
+
maxHeight: '24rem',
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
fixedColumns: {
|
|
189
|
+
enabled: false,
|
|
190
|
+
columns: '',
|
|
191
|
+
mode: 'fixed', // fixed | stack
|
|
192
|
+
stackGap: 0,
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
columnResize: {
|
|
196
|
+
enabled: false,
|
|
197
|
+
minWidth: 80,
|
|
198
|
+
maxWidth: 600,
|
|
199
|
+
persist: false,
|
|
200
|
+
storageKey: '',
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
columnReorder: {
|
|
204
|
+
enabled: false,
|
|
205
|
+
persist: false,
|
|
206
|
+
storageKey: '',
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
columnVisibility: {
|
|
210
|
+
enabled: false,
|
|
211
|
+
controls: '',
|
|
212
|
+
minVisible: 1,
|
|
213
|
+
persist: false,
|
|
214
|
+
storageKey: '',
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
rowReorder: {
|
|
218
|
+
enabled: false,
|
|
219
|
+
mode: 'handle', // handle | row
|
|
220
|
+
handleSelector: '[data-row-reorder-handle]',
|
|
221
|
+
keyAttr: 'data-row-key',
|
|
222
|
+
persist: false,
|
|
223
|
+
storageKey: '',
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
selection: {
|
|
227
|
+
enabled: false,
|
|
228
|
+
click: true,
|
|
229
|
+
multiple: false,
|
|
230
|
+
},
|
|
231
|
+
|
|
232
|
+
expandable: {
|
|
233
|
+
enabled: false,
|
|
234
|
+
idAttr: 'data-expand-id',
|
|
235
|
+
parentAttr: 'data-expand-parent-id',
|
|
236
|
+
toggleSelector: '[data-expand-toggle]',
|
|
237
|
+
collapsed: true,
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
search: {
|
|
241
|
+
enabled: false,
|
|
242
|
+
input: '',
|
|
243
|
+
param: 'q',
|
|
244
|
+
debounce: 300,
|
|
245
|
+
resetPage: true,
|
|
246
|
+
trim: true,
|
|
247
|
+
fields: [],
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
filters: {
|
|
251
|
+
enabled: false,
|
|
252
|
+
form: '',
|
|
253
|
+
debounce: 300,
|
|
254
|
+
apply: 'auto', // auto | manual
|
|
255
|
+
resetPage: true,
|
|
256
|
+
skipEmpty: true,
|
|
257
|
+
trim: true,
|
|
258
|
+
defaultOperator: 'eq',
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
state: {
|
|
262
|
+
enabled: true,
|
|
263
|
+
},
|
|
264
|
+
|
|
265
|
+
urlState: {
|
|
266
|
+
enabled: false,
|
|
267
|
+
read: true,
|
|
268
|
+
write: true,
|
|
269
|
+
listen: true,
|
|
270
|
+
mode: 'replace', // replace | push
|
|
271
|
+
prefix: '',
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
loading: {
|
|
275
|
+
enabled: true,
|
|
276
|
+
minDelay: 500,
|
|
277
|
+
skeleton: 5,
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
request: {
|
|
281
|
+
route: '',
|
|
282
|
+
method: 'GET',
|
|
283
|
+
credentials: 'same-origin',
|
|
284
|
+
headers: {'Accept': 'application/json'},
|
|
285
|
+
params: {},
|
|
286
|
+
parammap: {},
|
|
287
|
+
responsemode: 'data', // data | view | auto
|
|
288
|
+
datapath: 'data',
|
|
289
|
+
metapath: 'meta',
|
|
290
|
+
viewpath: 'view.tbody',
|
|
291
|
+
viewparam: 'view',
|
|
292
|
+
viewvalue: 'rows',
|
|
293
|
+
fieldsparam: 'fields',
|
|
294
|
+
cache: {
|
|
295
|
+
enable: true,
|
|
296
|
+
ttl: 30000,
|
|
297
|
+
max: 30,
|
|
298
|
+
},
|
|
299
|
+
export: {
|
|
300
|
+
route: '',
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Сортировка
|
|
307
|
+
|
|
308
|
+
По умолчанию сортировка включена для обычных таблиц. Поле определяется по `data-field`, тип — автоматически или через `data-sort-type`.
|
|
309
|
+
|
|
310
|
+
```html
|
|
311
|
+
<th data-field="created_at" data-sort-type="date">Создано</th>
|
|
312
|
+
<th data-field="total" data-sort-type="number">Сумма</th>
|
|
313
|
+
<th data-field="actions" data-sort-enabled="false">Действия</th>
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Для значения, отличного от отображаемого текста, используется `data-sort-value`:
|
|
317
|
+
|
|
318
|
+
```html
|
|
319
|
+
<td data-sort-value="2026-08-22">22 августа 2026</td>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
При `sort.multiple: true` следующая колонка добавляется с `Shift`. Если `multipleWithShift` равен `false`, мультисортировка действует постоянно.
|
|
323
|
+
|
|
324
|
+
Таблица с `colspan` или `rowspan` считается сложной. Для неё сортировка и операции, меняющие структуру колонок, отключаются автоматически, чтобы не нарушить сетку.
|
|
325
|
+
|
|
326
|
+
## Пагинация
|
|
327
|
+
|
|
328
|
+
Панель пагинации создаётся вне `.vg-table-container`, поэтому не попадает в горизонтальную прокрутку таблицы.
|
|
329
|
+
|
|
330
|
+
```html
|
|
331
|
+
<table
|
|
332
|
+
class="vg-table"
|
|
333
|
+
data-vg-table
|
|
334
|
+
data-pagination-enabled="true"
|
|
335
|
+
data-pagination-per-page="10"
|
|
336
|
+
data-pagination-position="bottom"
|
|
337
|
+
data-pagination-align="right"
|
|
338
|
+
data-pagination-show-per-page="true"
|
|
339
|
+
data-pagination-per-page-options="10,25,50,100"
|
|
340
|
+
></table>
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Выбор количества строк использует `VGDropdown`, но поле также принимает произвольное число от `1` до `pagination.max`. Текущая страница и размер страницы могут сохраняться в `localStorage`.
|
|
344
|
+
|
|
345
|
+
## Поиск, фильтры и состояния
|
|
346
|
+
|
|
347
|
+
### Поиск
|
|
348
|
+
|
|
349
|
+
```html
|
|
350
|
+
<input id="orders-search" class="form-control" type="search">
|
|
351
|
+
<button type="button" data-search-reset>Очистить</button>
|
|
352
|
+
|
|
353
|
+
<table
|
|
354
|
+
class="vg-table"
|
|
355
|
+
data-vg-table
|
|
356
|
+
data-search-enable="true"
|
|
357
|
+
data-search-input="#orders-search"
|
|
358
|
+
data-search-fields="name,status"
|
|
359
|
+
></table>
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
В локальном режиме поиск фильтрует существующие строки, в Remote-режиме передаёт значение на сервер параметром `q` или именем из `search.param`.
|
|
363
|
+
|
|
364
|
+
### Фильтры
|
|
365
|
+
|
|
366
|
+
```html
|
|
367
|
+
<form id="orders-filters">
|
|
368
|
+
<select data-filter-field="status">
|
|
369
|
+
<option value="">Все статусы</option>
|
|
370
|
+
<option value="active">Активные</option>
|
|
371
|
+
</select>
|
|
372
|
+
|
|
373
|
+
<input
|
|
374
|
+
type="number"
|
|
375
|
+
data-filter-field="total"
|
|
376
|
+
data-filter-operator="gte"
|
|
377
|
+
placeholder="Сумма от"
|
|
378
|
+
>
|
|
379
|
+
|
|
380
|
+
<button type="button" data-filter-reset>Сбросить фильтры</button>
|
|
381
|
+
</form>
|
|
382
|
+
|
|
383
|
+
<table
|
|
384
|
+
class="vg-table"
|
|
385
|
+
data-vg-table
|
|
386
|
+
data-filters-enable="true"
|
|
387
|
+
data-filters-form="#orders-filters"
|
|
388
|
+
data-filters-apply="auto"
|
|
389
|
+
></table>
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Доступные операторы: `eq`, `neq`, `contains`, `starts`, `ends`, `gt`, `gte`, `lt`, `lte`, `in`, `notin`.
|
|
393
|
+
|
|
394
|
+
Кнопка сброса очищает фильтры и глобальный поиск. При отсутствии результата компонент различает обычное пустое состояние и `filtered-empty`.
|
|
395
|
+
|
|
396
|
+
### Состояния
|
|
397
|
+
|
|
398
|
+
Встроенный state-layer поддерживает:
|
|
399
|
+
|
|
400
|
+
- `empty` — исходных строк нет;
|
|
401
|
+
- `filtered-empty` — строки не найдены после поиска или фильтрации;
|
|
402
|
+
- `error` — Remote-запрос завершился ошибкой;
|
|
403
|
+
- повтор запроса из состояния ошибки;
|
|
404
|
+
- сброс поиска и фильтров из `filtered-empty`.
|
|
405
|
+
|
|
406
|
+
Тексты задаются через `state.labels` или соответствующие `data-state-*-label`.
|
|
407
|
+
|
|
408
|
+
## Состояние в URL
|
|
409
|
+
|
|
410
|
+
Общий URL state синхронизирует `page`, `perPage`, `sort`, `dir`, `search` и фильтры:
|
|
411
|
+
|
|
412
|
+
```html
|
|
413
|
+
<table
|
|
414
|
+
class="vg-table"
|
|
415
|
+
data-vg-table
|
|
416
|
+
data-url-state-enable="true"
|
|
417
|
+
data-url-state-mode="replace"
|
|
418
|
+
data-url-state-prefix="orders-"
|
|
419
|
+
></table>
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Для нескольких таблиц на одной странице обязательно задавайте разные `urlState.prefix`. Компонент умеет читать исходный query string, записывать изменения и обрабатывать переходы Back/Forward.
|
|
423
|
+
|
|
424
|
+
## Фиксированный заголовок
|
|
425
|
+
|
|
426
|
+
VGTable использует нативный `position: sticky` и отдельный header-слой без клонирования строк и обработчиков.
|
|
427
|
+
|
|
428
|
+
### Прокрутка внутри таблицы
|
|
429
|
+
|
|
430
|
+
```html
|
|
431
|
+
<table
|
|
432
|
+
class="vg-table"
|
|
433
|
+
data-vg-table
|
|
434
|
+
data-sticky-header-enabled="true"
|
|
435
|
+
data-sticky-header-mode="container"
|
|
436
|
+
data-sticky-header-max-height="28rem"
|
|
437
|
+
></table>
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Прокрутка страницы
|
|
441
|
+
|
|
442
|
+
```html
|
|
443
|
+
<table
|
|
444
|
+
class="vg-table"
|
|
445
|
+
data-vg-table
|
|
446
|
+
data-sticky-header-enabled="true"
|
|
447
|
+
data-sticky-header-mode="page"
|
|
448
|
+
data-sticky-header-top="72"
|
|
449
|
+
></table>
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
`stickyHeader.top` принимает число пикселей или CSS-значение. Если параметр равен `null`, отступом можно управлять публичной переменной `--vg-table-sticky-top`, например с учётом фиксированного header сайта.
|
|
453
|
+
|
|
454
|
+
## Фиксированные колонки
|
|
455
|
+
|
|
456
|
+
Колонки задаются по `data-field` или zero-based индексу:
|
|
457
|
+
|
|
458
|
+
```html
|
|
459
|
+
<table
|
|
460
|
+
class="vg-table"
|
|
461
|
+
data-vg-table
|
|
462
|
+
data-fixed-columns-enabled="true"
|
|
463
|
+
data-fixed-columns="left:id,name;right:actions"
|
|
464
|
+
data-fixed-columns-mode="fixed"
|
|
465
|
+
></table>
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Поддерживаются режимы:
|
|
469
|
+
|
|
470
|
+
- `fixed` — колонки постоянно закреплены у соответствующего края;
|
|
471
|
+
- `stack` — колонки последовательно фиксируются при прокрутке.
|
|
472
|
+
|
|
473
|
+
Отдельную колонку также можно пометить непосредственно в заголовке. Фиксированные ячейки получают непрозрачный фон и повышенный `z-index`, чтобы соседние колонки не просвечивали при прокрутке.
|
|
474
|
+
|
|
475
|
+
## Управление колонками
|
|
476
|
+
|
|
477
|
+
Для изменения ширины, перестановки и видимости каждой колонке нужен стабильный `data-field`.
|
|
478
|
+
|
|
479
|
+
```html
|
|
480
|
+
<div id="column-controls">
|
|
481
|
+
<label><input type="checkbox" data-vg-table-column="email" checked> Почта</label>
|
|
482
|
+
<label><input type="checkbox" data-vg-table-column="city" checked> Город</label>
|
|
483
|
+
</div>
|
|
484
|
+
|
|
485
|
+
<table
|
|
486
|
+
class="vg-table"
|
|
487
|
+
data-vg-table
|
|
488
|
+
data-column-resize-enable="true"
|
|
489
|
+
data-column-reorder-enable="true"
|
|
490
|
+
data-column-visibility-enable="true"
|
|
491
|
+
data-column-visibility-controls="#column-controls"
|
|
492
|
+
></table>
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
Все три режима могут независимо сохранять состояние в `localStorage`. Фиксированные колонки разрешено изменять по ширине, но нельзя скрывать или переносить через границу фиксированной области.
|
|
496
|
+
|
|
497
|
+
## Перестановка строк
|
|
498
|
+
|
|
499
|
+
```html
|
|
500
|
+
<table
|
|
501
|
+
class="vg-table"
|
|
502
|
+
data-vg-table
|
|
503
|
+
data-row-reorder-enable="true"
|
|
504
|
+
data-row-reorder-mode="handle"
|
|
505
|
+
>
|
|
506
|
+
<tbody>
|
|
507
|
+
<tr data-row-key="order-1">
|
|
508
|
+
<td><button type="button" data-row-reorder-handle>Переместить</button></td>
|
|
509
|
+
<td>Заказ №1</td>
|
|
510
|
+
</tr>
|
|
511
|
+
</tbody>
|
|
512
|
+
</table>
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
Режим `handle` начинает перенос только с указанного элемента, `row` — с любой неинтерактивной области строки. При включённой перестановке строк сортировка не инициализируется: ручной порядок и сортировка являются взаимоисключающими режимами.
|
|
516
|
+
|
|
517
|
+
## Выбор строк
|
|
518
|
+
|
|
519
|
+
```js
|
|
520
|
+
const table = VGTable.getOrCreateInstance(element, {
|
|
521
|
+
selection: {
|
|
522
|
+
enabled: true,
|
|
523
|
+
click: true,
|
|
524
|
+
multiple: true,
|
|
525
|
+
},
|
|
526
|
+
});
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
Клики по ссылкам, кнопкам и полям формы внутри строки не изменяют выбор. Текущее состояние доступно через `getSelectedRows()`.
|
|
530
|
+
|
|
531
|
+
## Раскрываемые строки
|
|
532
|
+
|
|
533
|
+
Связи дерева задаются ID строки и ID родителя. Уровень вложенности не ограничен разметкой одного уровня.
|
|
534
|
+
|
|
535
|
+
```html
|
|
536
|
+
<table
|
|
537
|
+
class="vg-table"
|
|
538
|
+
data-vg-table
|
|
539
|
+
data-expandable-enabled="true"
|
|
540
|
+
data-expandable-collapsed="true"
|
|
541
|
+
>
|
|
542
|
+
<tbody>
|
|
543
|
+
<tr data-expand-id="root">
|
|
544
|
+
<td><button type="button" data-expand-toggle></button> Родитель</td>
|
|
545
|
+
</tr>
|
|
546
|
+
<tr data-expand-id="child" data-expand-parent-id="root">
|
|
547
|
+
<td>Дочерняя строка</td>
|
|
548
|
+
</tr>
|
|
549
|
+
<tr data-expand-id="leaf" data-expand-parent-id="child">
|
|
550
|
+
<td>Третий уровень</td>
|
|
551
|
+
</tr>
|
|
552
|
+
</tbody>
|
|
553
|
+
</table>
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
Если кнопка управления не добавлена вручную, компонент создаёт её для родительской строки автоматически.
|
|
557
|
+
|
|
558
|
+
## Remote-режим
|
|
559
|
+
|
|
560
|
+
Непустой `request.route` автоматически переводит таблицу в Remote-режим. Запросы выполняются через общий Ajax-компонент VGApp.
|
|
561
|
+
|
|
562
|
+
```html
|
|
563
|
+
<table
|
|
564
|
+
id="remote-orders"
|
|
565
|
+
class="vg-table"
|
|
566
|
+
data-vg-table
|
|
567
|
+
data-request-route="/api/orders"
|
|
568
|
+
data-request-method="GET"
|
|
569
|
+
data-request-responsemode="data"
|
|
570
|
+
data-request-datapath="data"
|
|
571
|
+
data-request-metapath="meta"
|
|
572
|
+
data-request-cache-enable="true"
|
|
573
|
+
data-pagination-enabled="true"
|
|
574
|
+
data-pagination-show-per-page="true"
|
|
575
|
+
></table>
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
Компонент передаёт серверу:
|
|
579
|
+
|
|
580
|
+
- `page` — текущую страницу;
|
|
581
|
+
- `per_page` — количество строк;
|
|
582
|
+
- `sort` — поле или список полей через запятую;
|
|
583
|
+
- `dir` — направление или список направлений через запятую;
|
|
584
|
+
- параметр поиска, по умолчанию `q`;
|
|
585
|
+
- параметры активных фильтров;
|
|
586
|
+
- дополнительные значения из `request.params`.
|
|
587
|
+
|
|
588
|
+
Имена можно переопределить через `request.parammap`:
|
|
589
|
+
|
|
590
|
+
```js
|
|
591
|
+
request: {
|
|
592
|
+
route: '/api/orders',
|
|
593
|
+
parammap: {
|
|
594
|
+
q: 'search',
|
|
595
|
+
per_page: 'limit',
|
|
596
|
+
},
|
|
597
|
+
}
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### Ответ с данными
|
|
601
|
+
|
|
602
|
+
```json
|
|
603
|
+
{
|
|
604
|
+
"data": [
|
|
605
|
+
{
|
|
606
|
+
"id": 1,
|
|
607
|
+
"name": "Заказ №1",
|
|
608
|
+
"status": "active"
|
|
609
|
+
}
|
|
610
|
+
],
|
|
611
|
+
"meta": {
|
|
612
|
+
"current_page": 1,
|
|
613
|
+
"per_page": 10,
|
|
614
|
+
"total": 100,
|
|
615
|
+
"last_page": 10
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
Ключи объектов сопоставляются с заголовками `th[data-field]`. Путь к массиву и meta можно изменить через `datapath` и `metapath`.
|
|
621
|
+
|
|
622
|
+
### Ответ с готовой разметкой
|
|
623
|
+
|
|
624
|
+
Для `responsemode: 'view'` сервер возвращает HTML строк:
|
|
625
|
+
|
|
626
|
+
```json
|
|
627
|
+
{
|
|
628
|
+
"view": {
|
|
629
|
+
"tbody": "<tr data-row-key=\"1\"><td>1</td><td>Заказ №1</td></tr>"
|
|
630
|
+
},
|
|
631
|
+
"meta": {
|
|
632
|
+
"page": 1,
|
|
633
|
+
"per_page": 10,
|
|
634
|
+
"total": 100,
|
|
635
|
+
"pages": 10
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
В режиме `auto` компонент сначала ищет server-rendered view, затем массив данных. Для view-запроса автоматически передаются имя представления и список полей, если настроены `viewparam`, `viewvalue` и `fieldsparam`.
|
|
641
|
+
|
|
642
|
+
Повторяющиеся запросы кратковременно кешируются в памяти экземпляра. Для выгрузки текущего серверного состояния используется отдельный `request.export.route` или основной route.
|
|
643
|
+
|
|
644
|
+
## Группы параметров
|
|
645
|
+
|
|
646
|
+
Повторяющуюся конфигурацию можно зарегистрировать один раз и подключать одним атрибутом:
|
|
647
|
+
|
|
648
|
+
```js
|
|
649
|
+
VGTable.registerParamsGroup('remote-registry', {
|
|
650
|
+
pagination: {
|
|
651
|
+
enabled: true,
|
|
652
|
+
size: {enabled: true},
|
|
653
|
+
},
|
|
654
|
+
loading: {
|
|
655
|
+
enabled: true,
|
|
656
|
+
skeleton: 10,
|
|
657
|
+
},
|
|
658
|
+
urlState: {
|
|
659
|
+
enabled: true,
|
|
660
|
+
},
|
|
661
|
+
});
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
```html
|
|
665
|
+
<table
|
|
666
|
+
class="vg-table"
|
|
667
|
+
data-vg-table
|
|
668
|
+
data-group-params="remote-registry"
|
|
669
|
+
data-request-route="/api/orders"
|
|
670
|
+
></table>
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
Параметры конкретного экземпляра и его Data API дополняют или переопределяют зарегистрированную группу.
|
|
674
|
+
|
|
675
|
+
Доступные методы:
|
|
676
|
+
|
|
677
|
+
```js
|
|
678
|
+
VGTable.registerParamsGroup(name, params);
|
|
679
|
+
VGTable.getParamsGroup(name);
|
|
680
|
+
VGTable.unregisterParamsGroup(name);
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
## Интернационализация
|
|
684
|
+
|
|
685
|
+
Встроены локали `ru` и `en`. Региональный код, например `ru-RU`, использует точное совпадение, а затем базовую локаль `ru`.
|
|
686
|
+
|
|
687
|
+
```js
|
|
688
|
+
const table = VGTable.getOrCreateInstance(element, {
|
|
689
|
+
locale: 'en',
|
|
690
|
+
i18n: {
|
|
691
|
+
en: {
|
|
692
|
+
pagination: {
|
|
693
|
+
size: {
|
|
694
|
+
label: 'Rows per page',
|
|
695
|
+
},
|
|
696
|
+
},
|
|
697
|
+
},
|
|
698
|
+
},
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
table.init();
|
|
702
|
+
table.setLocale('ru');
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
Пользовательский словарь объединяется со встроенным, поэтому достаточно указать только изменяемые строки.
|
|
706
|
+
|
|
707
|
+
## Публичные методы
|
|
708
|
+
|
|
709
|
+
### Экземпляр и жизненный цикл
|
|
710
|
+
|
|
711
|
+
```js
|
|
712
|
+
VGTable.getInstance(element);
|
|
713
|
+
VGTable.getOrCreateInstance(element, params);
|
|
714
|
+
|
|
715
|
+
table.init();
|
|
716
|
+
table.dispose();
|
|
717
|
+
table.isRemote();
|
|
718
|
+
table.isComplex();
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
### Локаль
|
|
722
|
+
|
|
723
|
+
```js
|
|
724
|
+
table.getLocale();
|
|
725
|
+
table.setLocale(locale);
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
### Сортировка
|
|
729
|
+
|
|
730
|
+
```js
|
|
731
|
+
table.setSort(field, direction);
|
|
732
|
+
table.setSorts(sorts);
|
|
733
|
+
table.getSort();
|
|
734
|
+
table.getSorts();
|
|
735
|
+
table.clearSort();
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
### Пагинация
|
|
739
|
+
|
|
740
|
+
```js
|
|
741
|
+
table.setPage(page);
|
|
742
|
+
table.setPerPage(perPage);
|
|
743
|
+
table.getPagination();
|
|
744
|
+
table.refreshPagination();
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
### Поиск, фильтры и URL
|
|
748
|
+
|
|
749
|
+
```js
|
|
750
|
+
table.getSearch();
|
|
751
|
+
table.setSearch(value);
|
|
752
|
+
table.resetSearch();
|
|
753
|
+
table.refreshSearch();
|
|
754
|
+
|
|
755
|
+
table.getFilters();
|
|
756
|
+
table.setFilters(filters);
|
|
757
|
+
table.resetFilters();
|
|
758
|
+
table.refreshFilters();
|
|
759
|
+
|
|
760
|
+
table.getUrlState();
|
|
761
|
+
table.refreshUrlState();
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
### Состояния и Remote
|
|
765
|
+
|
|
766
|
+
```js
|
|
767
|
+
table.getTableState();
|
|
768
|
+
table.showTableState(state, message);
|
|
769
|
+
table.clearTableState();
|
|
770
|
+
|
|
771
|
+
table.reload();
|
|
772
|
+
table.setRequestParams(params);
|
|
773
|
+
table.getRequestState();
|
|
774
|
+
table.clearRequestCache();
|
|
775
|
+
table.exportRemote(format, options);
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
### Заголовок и колонки
|
|
779
|
+
|
|
780
|
+
```js
|
|
781
|
+
table.refreshStickyHeader();
|
|
782
|
+
table.refreshFixedColumns();
|
|
783
|
+
table.getFixedColumns();
|
|
784
|
+
|
|
785
|
+
table.getColumns();
|
|
786
|
+
table.setColumnWidth(field, width);
|
|
787
|
+
table.moveColumn(field, target);
|
|
788
|
+
table.setColumnVisible(field, visible);
|
|
789
|
+
table.resetColumns();
|
|
790
|
+
table.refreshColumns();
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
### Строки
|
|
794
|
+
|
|
795
|
+
```js
|
|
796
|
+
table.selectRow(row, selected);
|
|
797
|
+
table.toggleRow(row);
|
|
798
|
+
table.getSelectedRows();
|
|
799
|
+
table.clearSelection();
|
|
800
|
+
|
|
801
|
+
table.toggleExpanded(id);
|
|
802
|
+
table.expandRow(id);
|
|
803
|
+
table.collapseRow(id);
|
|
804
|
+
table.getExpandable();
|
|
805
|
+
table.refreshExpandable();
|
|
806
|
+
|
|
807
|
+
table.getRowOrder();
|
|
808
|
+
table.moveRow(row, target, position, emit);
|
|
809
|
+
table.resetRows();
|
|
810
|
+
table.refreshRowReorder();
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
## События
|
|
814
|
+
|
|
815
|
+
Все события всплывают от элемента таблицы и доступны через `event.detail`.
|
|
816
|
+
|
|
817
|
+
| Событие | Назначение |
|
|
818
|
+
| --- | --- |
|
|
819
|
+
| `sortchange.vg.table` | Изменилось поле, направление или порядок мультисортировки |
|
|
820
|
+
| `pagechange.vg.table` | Изменилась текущая страница |
|
|
821
|
+
| `perpagechange.vg.table` | Изменилось количество строк на странице |
|
|
822
|
+
| `searchchange.vg.table` | Изменился глобальный поиск |
|
|
823
|
+
| `filterschange.vg.table` | Изменились активные фильтры |
|
|
824
|
+
| `selectionchange.vg.table` | Изменился выбор строк |
|
|
825
|
+
| `rowtoggle.vg.table` | Изменилось состояние раскрываемой ветви |
|
|
826
|
+
| `rowexpand.vg.table` | Ветвь развёрнута |
|
|
827
|
+
| `rowcollapse.vg.table` | Ветвь свёрнута |
|
|
828
|
+
| `rowreorder.vg.table` | Изменён порядок строк |
|
|
829
|
+
| `columnresize.vg.table` | Изменена ширина колонки |
|
|
830
|
+
| `columnreorder.vg.table` | Изменён порядок колонок |
|
|
831
|
+
| `columnvisibilitychange.vg.table` | Изменена видимость колонки |
|
|
832
|
+
| `beforeload.vg.table` | Remote-запрос подготовлен к отправке |
|
|
833
|
+
| `requestsuccess.vg.table` | Получен успешный Remote-ответ |
|
|
834
|
+
| `requesterror.vg.table` | Remote-запрос завершился ошибкой |
|
|
835
|
+
| `dataloaded.vg.table` | Данные ответа прочитаны |
|
|
836
|
+
| `afterrender.vg.table` | Строки ответа отрисованы |
|
|
837
|
+
| `statechange.vg.table` | Изменилось состояние результата |
|
|
838
|
+
| `urlstateread.vg.table` | Состояние прочитано из URL |
|
|
839
|
+
| `urlstatewrite.vg.table` | Состояние записано в URL |
|
|
840
|
+
| `urlstateerror.vg.table` | Возникла ошибка разбора URL state |
|
|
841
|
+
| `localechange.vg.table` | Изменилась активная локаль |
|
|
842
|
+
|
|
843
|
+
```js
|
|
844
|
+
element.addEventListener('sortchange.vg.table', (event) => {
|
|
845
|
+
console.log(event.detail.sorts);
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
element.addEventListener('requesterror.vg.table', (event) => {
|
|
849
|
+
console.error(event.detail.error);
|
|
850
|
+
});
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
## Размеры и оформление
|
|
854
|
+
|
|
855
|
+
Доступные классы размеров:
|
|
856
|
+
|
|
857
|
+
```html
|
|
858
|
+
<table class="vg-table vg-table-xs"></table>
|
|
859
|
+
<table class="vg-table vg-table-sm"></table>
|
|
860
|
+
<table class="vg-table"></table>
|
|
861
|
+
<table class="vg-table vg-table-lg"></table>
|
|
862
|
+
<table class="vg-table vg-table-xl"></table>
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
Средний размер является значением по умолчанию и не требует класса `vg-table-md`.
|
|
866
|
+
|
|
867
|
+
Дополнительные классы:
|
|
868
|
+
|
|
869
|
+
- `.vg-table-striped` — чередование фона строк;
|
|
870
|
+
- `.vg-table-hovered` — подсветка строки при наведении.
|
|
871
|
+
|
|
872
|
+
Для темизации доступны группы CSS-переменных:
|
|
873
|
+
|
|
874
|
+
- `--vg-table-*` — таблица и ячейки;
|
|
875
|
+
- `--vg-table-wrapper-*` — внешний wrapper;
|
|
876
|
+
- `--vg-table-container-*` — scroll-контейнер;
|
|
877
|
+
- `--vg-table-sort-*` — сортировка;
|
|
878
|
+
- `--vg-table-columns-*` — управление колонками;
|
|
879
|
+
- `--vg-table-row-reorder-*` — перестановка строк;
|
|
880
|
+
- `--vg-table-pan-*` — горизонтальное перемещение;
|
|
881
|
+
- `--vg-table-selection-*` — выбранные строки;
|
|
882
|
+
- `--vg-table-expandable-*` — раскрываемое дерево;
|
|
883
|
+
- `--vg-table-pagination-*` — пагинация;
|
|
884
|
+
- `--vg-table-sticky-*` — фиксированный заголовок;
|
|
885
|
+
- `--vg-table-fixed-*` — фиксированные колонки;
|
|
886
|
+
- `--vg-table-state-*` — состояния результата;
|
|
887
|
+
- `--vg-table-skeleton-*` — skeleton загрузки.
|
|
888
|
+
|
|
889
|
+
```css
|
|
890
|
+
.orders-table {
|
|
891
|
+
--vg-table-sticky-top: 4.5rem;
|
|
892
|
+
--vg-table-pagination-gap: 0.75rem;
|
|
893
|
+
}
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
## Доступность и клавиатура
|
|
897
|
+
|
|
898
|
+
- сортируемые заголовки поддерживают `Enter` и `Space`;
|
|
899
|
+
- resize-handle колонок поддерживает стрелки, `Home` и `End`;
|
|
900
|
+
- handle перестановки строк поддерживает стрелки вверх/вниз, `Home` и `End`;
|
|
901
|
+
- кнопки раскрываемых ветвей получают `aria-expanded` и локализованную подпись;
|
|
902
|
+
- активная страница отмечается `aria-current="page"`;
|
|
903
|
+
- шевроны пагинации имеют текстовые `aria-label`;
|
|
904
|
+
- состояние таблицы и интерактивные контролы обновляются без удаления исходной семантики `<table>`.
|
|
905
|
+
|
|
906
|
+
## Важные сочетания режимов
|
|
907
|
+
|
|
908
|
+
- `colspan` и `rowspan` автоматически помечают таблицу как сложную и отключают сортировку, фиксированные колонки и структурное управление колонками;
|
|
909
|
+
- самостоятельная перестановка строк отключает сортировку;
|
|
910
|
+
- внешний wrapper отвечает за панели, внутренний container — только за прокрутку таблицы;
|
|
911
|
+
- для Remote-таблицы `data-field` должны совпадать с ключами данных или сервер должен возвращать готовый view;
|
|
912
|
+
- для сохранения колонок и строк нужны стабильные `data-field` и `data-row-key`;
|
|
913
|
+
- после ручного изменения DOM вызывайте соответствующий метод `refresh*()`.
|
|
914
|
+
|
|
915
|
+
## Удаление экземпляра
|
|
916
|
+
|
|
917
|
+
```js
|
|
918
|
+
const table = VGTable.getInstance(element);
|
|
919
|
+
table?.dispose();
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
`dispose()` удаляет созданные компонентом обработчики и служебные элементы, восстанавливает исходную структуру таблицы и удаляет только те wrapper/container, которые VGTable создал самостоятельно.
|