@vaadin/crud 23.3.3 → 24.0.0-alpha10
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/package.json +12 -12
- package/src/vaadin-crud-dialog.js +1 -1
- package/src/vaadin-crud-edit-column.d.ts +1 -1
- package/src/vaadin-crud-edit-column.js +2 -2
- package/src/vaadin-crud-edit.d.ts +1 -1
- package/src/vaadin-crud-edit.js +1 -1
- package/src/vaadin-crud-form.d.ts +1 -1
- package/src/vaadin-crud-form.js +3 -25
- package/src/vaadin-crud-grid.d.ts +1 -1
- package/src/vaadin-crud-grid.js +14 -35
- package/src/vaadin-crud-helpers.d.ts +29 -0
- package/src/vaadin-crud-helpers.js +64 -0
- package/src/vaadin-crud-include-mixin.d.ts +1 -1
- package/src/vaadin-crud-include-mixin.js +7 -4
- package/src/vaadin-crud.d.ts +5 -6
- package/src/vaadin-crud.js +153 -156
- package/theme/material/vaadin-crud-styles.js +0 -7
- package/web-types.json +6 -6
- package/web-types.lit.json +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/crud",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "24.0.0-alpha10",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -37,16 +37,16 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
39
39
|
"@polymer/polymer": "^3.0.0",
|
|
40
|
-
"@vaadin/button": "
|
|
41
|
-
"@vaadin/component-base": "
|
|
42
|
-
"@vaadin/confirm-dialog": "
|
|
43
|
-
"@vaadin/dialog": "
|
|
44
|
-
"@vaadin/form-layout": "
|
|
45
|
-
"@vaadin/grid": "
|
|
46
|
-
"@vaadin/text-field": "
|
|
47
|
-
"@vaadin/vaadin-lumo-styles": "
|
|
48
|
-
"@vaadin/vaadin-material-styles": "
|
|
49
|
-
"@vaadin/vaadin-themable-mixin": "
|
|
40
|
+
"@vaadin/button": "24.0.0-alpha10",
|
|
41
|
+
"@vaadin/component-base": "24.0.0-alpha10",
|
|
42
|
+
"@vaadin/confirm-dialog": "24.0.0-alpha10",
|
|
43
|
+
"@vaadin/dialog": "24.0.0-alpha10",
|
|
44
|
+
"@vaadin/form-layout": "24.0.0-alpha10",
|
|
45
|
+
"@vaadin/grid": "24.0.0-alpha10",
|
|
46
|
+
"@vaadin/text-field": "24.0.0-alpha10",
|
|
47
|
+
"@vaadin/vaadin-lumo-styles": "24.0.0-alpha10",
|
|
48
|
+
"@vaadin/vaadin-material-styles": "24.0.0-alpha10",
|
|
49
|
+
"@vaadin/vaadin-themable-mixin": "24.0.0-alpha10"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@esm-bundle/chai": "^4.3.4",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"web-types.json",
|
|
59
59
|
"web-types.lit.json"
|
|
60
60
|
],
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "2e04534d8b47bcd216f89b5f849bafef1a73b174"
|
|
62
62
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2000 -
|
|
3
|
+
* Copyright (c) 2000 - 2023 Vaadin Ltd.
|
|
4
4
|
*
|
|
5
5
|
* This program is available under Vaadin Commercial License and Service Terms.
|
|
6
6
|
*
|
|
@@ -41,7 +41,7 @@ class CrudEditColumn extends GridColumn {
|
|
|
41
41
|
*/
|
|
42
42
|
width: {
|
|
43
43
|
type: String,
|
|
44
|
-
value: '
|
|
44
|
+
value: '4rem',
|
|
45
45
|
},
|
|
46
46
|
|
|
47
47
|
/**
|
package/src/vaadin-crud-edit.js
CHANGED
package/src/vaadin-crud-form.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2000 -
|
|
3
|
+
* Copyright (c) 2000 - 2023 Vaadin Ltd.
|
|
4
4
|
*
|
|
5
5
|
* This program is available under Vaadin Commercial License and Service Terms.
|
|
6
6
|
*
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import '@vaadin/text-field/src/vaadin-text-field.js';
|
|
12
12
|
import { FormLayout } from '@vaadin/form-layout/src/vaadin-form-layout.js';
|
|
13
|
+
import { capitalize } from './vaadin-crud-helpers.js';
|
|
13
14
|
import { IncludedMixin } from './vaadin-crud-include-mixin.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -62,7 +63,7 @@ class CrudForm extends IncludedMixin(FormLayout) {
|
|
|
62
63
|
/** @private */
|
|
63
64
|
__createField(parent, path) {
|
|
64
65
|
const field = document.createElement('vaadin-text-field');
|
|
65
|
-
field.label =
|
|
66
|
+
field.label = capitalize(path);
|
|
66
67
|
field.path = path;
|
|
67
68
|
field.required = true;
|
|
68
69
|
parent.appendChild(field);
|
|
@@ -87,29 +88,6 @@ class CrudForm extends IncludedMixin(FormLayout) {
|
|
|
87
88
|
this._fields = undefined;
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
|
-
|
|
91
|
-
/** @private */
|
|
92
|
-
__capitalize(path) {
|
|
93
|
-
return path
|
|
94
|
-
.toLowerCase()
|
|
95
|
-
.replace(/([^\w]+)/g, ' ')
|
|
96
|
-
.trim()
|
|
97
|
-
.replace(/^./, (c) => c.toUpperCase());
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/** @private */
|
|
101
|
-
__set(path, val, obj) {
|
|
102
|
-
if (obj && path) {
|
|
103
|
-
path
|
|
104
|
-
.split('.')
|
|
105
|
-
.slice(0, -1)
|
|
106
|
-
.reduce((o, p) => {
|
|
107
|
-
o[p] = o[p] || {};
|
|
108
|
-
return o[p];
|
|
109
|
-
}, obj);
|
|
110
|
-
this.set(path, val, obj);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
91
|
}
|
|
114
92
|
|
|
115
93
|
customElements.define(CrudForm.is, CrudForm);
|
package/src/vaadin-crud-grid.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2000 -
|
|
3
|
+
* Copyright (c) 2000 - 2023 Vaadin Ltd.
|
|
4
4
|
*
|
|
5
5
|
* This program is available under Vaadin Commercial License and Service Terms.
|
|
6
6
|
*
|
|
@@ -14,6 +14,7 @@ import '@vaadin/grid/src/vaadin-grid-sorter.js';
|
|
|
14
14
|
import '@vaadin/grid/src/vaadin-grid-filter.js';
|
|
15
15
|
import './vaadin-crud-edit-column.js';
|
|
16
16
|
import { Grid } from '@vaadin/grid/src/vaadin-grid.js';
|
|
17
|
+
import { capitalize, getProperty } from './vaadin-crud-helpers.js';
|
|
17
18
|
import { IncludedMixin } from './vaadin-crud-include-mixin.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -73,13 +74,15 @@ class CrudGrid extends IncludedMixin(Grid) {
|
|
|
73
74
|
|
|
74
75
|
/** @private */
|
|
75
76
|
__toggleEditColumn() {
|
|
76
|
-
|
|
77
|
+
let editColumn = this.querySelector('vaadin-crud-edit-column');
|
|
77
78
|
if (this.hideEditColumn) {
|
|
78
|
-
if (
|
|
79
|
-
this.removeChild(
|
|
79
|
+
if (editColumn) {
|
|
80
|
+
this.removeChild(editColumn);
|
|
80
81
|
}
|
|
81
|
-
} else if (!
|
|
82
|
-
|
|
82
|
+
} else if (!editColumn) {
|
|
83
|
+
editColumn = document.createElement('vaadin-crud-edit-column');
|
|
84
|
+
editColumn.frozenToEnd = true;
|
|
85
|
+
this.appendChild(editColumn);
|
|
83
86
|
}
|
|
84
87
|
}
|
|
85
88
|
|
|
@@ -146,10 +149,10 @@ class CrudGrid extends IncludedMixin(Grid) {
|
|
|
146
149
|
_generateHeader(path) {
|
|
147
150
|
return path
|
|
148
151
|
.substr(path.lastIndexOf('.') + 1)
|
|
149
|
-
.replace(/([A-Z])/
|
|
152
|
+
.replace(/([A-Z])/gu, '-$1')
|
|
150
153
|
.toLowerCase()
|
|
151
|
-
.replace(/-/
|
|
152
|
-
.replace(
|
|
154
|
+
.replace(/-/gu, ' ')
|
|
155
|
+
.replace(/^./u, (match) => match.toUpperCase());
|
|
153
156
|
}
|
|
154
157
|
|
|
155
158
|
/** @private */
|
|
@@ -167,7 +170,7 @@ class CrudGrid extends IncludedMixin(Grid) {
|
|
|
167
170
|
col = document.createElement('vaadin-grid-column');
|
|
168
171
|
parent.appendChild(col);
|
|
169
172
|
col.renderer = (root, _column, model) => {
|
|
170
|
-
root.textContent = path ?
|
|
173
|
+
root.textContent = path ? getProperty(path, model.item) : model.item;
|
|
171
174
|
};
|
|
172
175
|
}
|
|
173
176
|
|
|
@@ -199,7 +202,6 @@ class CrudGrid extends IncludedMixin(Grid) {
|
|
|
199
202
|
|
|
200
203
|
const textField = window.document.createElement('vaadin-text-field');
|
|
201
204
|
textField.setAttribute('theme', 'small');
|
|
202
|
-
textField.setAttribute('slot', 'filter');
|
|
203
205
|
textField.setAttribute('focus-target', true);
|
|
204
206
|
textField.style.width = '100%';
|
|
205
207
|
if (this.noSort) {
|
|
@@ -266,34 +268,11 @@ class CrudGrid extends IncludedMixin(Grid) {
|
|
|
266
268
|
__createGroup(parent, header) {
|
|
267
269
|
const grp = document.createElement('vaadin-grid-column-group');
|
|
268
270
|
if (header) {
|
|
269
|
-
grp.header =
|
|
271
|
+
grp.header = capitalize(header);
|
|
270
272
|
}
|
|
271
273
|
parent.appendChild(grp);
|
|
272
274
|
return grp;
|
|
273
275
|
}
|
|
274
|
-
|
|
275
|
-
/** @private */
|
|
276
|
-
__capitalize(path) {
|
|
277
|
-
return path
|
|
278
|
-
.toLowerCase()
|
|
279
|
-
.replace(/([^\w]+)/g, ' ')
|
|
280
|
-
.trim()
|
|
281
|
-
.replace(/^./, (c) => c.toUpperCase());
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/** @private */
|
|
285
|
-
__set(path, val, obj) {
|
|
286
|
-
if (obj && path) {
|
|
287
|
-
path
|
|
288
|
-
.split('.')
|
|
289
|
-
.slice(0, -1)
|
|
290
|
-
.reduce((o, p) => {
|
|
291
|
-
o[p] = o[p] || {};
|
|
292
|
-
return o[p];
|
|
293
|
-
}, obj);
|
|
294
|
-
this.set(path, val, obj);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
276
|
}
|
|
298
277
|
|
|
299
278
|
customElements.define(CrudGrid.is, CrudGrid);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2000 - 2023 Vaadin Ltd.
|
|
4
|
+
*
|
|
5
|
+
* This program is available under Vaadin Commercial License and Service Terms.
|
|
6
|
+
*
|
|
7
|
+
*
|
|
8
|
+
* See https://vaadin.com/commercial-license-and-service-terms for the full
|
|
9
|
+
* license.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Convenience utility for capitalizing a string, with
|
|
14
|
+
* replacing non-alphanumeric characters with spaces.
|
|
15
|
+
*/
|
|
16
|
+
export function capitalize(path: string): string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Convenience method for reading a value from a path.
|
|
20
|
+
*/
|
|
21
|
+
export function getProperty(path: string, obj: Record<string, unknown>): unknown;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Convenience utility for setting a value to a path.
|
|
25
|
+
*
|
|
26
|
+
* Note, if any part in the path is undefined, this
|
|
27
|
+
* function initializes it with an empty object.
|
|
28
|
+
*/
|
|
29
|
+
export function setProperty(path: string, value: unknown, obj: Record<string, unknown>): void;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2000 - 2023 Vaadin Ltd.
|
|
4
|
+
*
|
|
5
|
+
* This program is available under Vaadin Commercial License and Service Terms.
|
|
6
|
+
*
|
|
7
|
+
*
|
|
8
|
+
* See https://vaadin.com/commercial-license-and-service-terms for the full
|
|
9
|
+
* license.
|
|
10
|
+
*/
|
|
11
|
+
import { get, set } from '@polymer/polymer/lib/utils/path.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Convenience utility for capitalizing a string, with
|
|
15
|
+
* replacing non-alphanumeric characters with spaces.
|
|
16
|
+
*
|
|
17
|
+
* @param {string} path
|
|
18
|
+
* @return {string}
|
|
19
|
+
*/
|
|
20
|
+
export function capitalize(path) {
|
|
21
|
+
return path
|
|
22
|
+
.toLowerCase()
|
|
23
|
+
.replace(/([^\w]+)/gu, ' ')
|
|
24
|
+
.trim()
|
|
25
|
+
.replace(/^./u, (c) => c.toUpperCase());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Convenience utility for reading a value from a path.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} path
|
|
32
|
+
* @param {Object} obj
|
|
33
|
+
* @return {*}
|
|
34
|
+
*/
|
|
35
|
+
export function getProperty(path, obj) {
|
|
36
|
+
return get(obj, path);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Convenience utility for setting a value to a path.
|
|
41
|
+
*
|
|
42
|
+
* Note, if any part in the path is undefined, this
|
|
43
|
+
* function initializes it with an empty object.
|
|
44
|
+
*
|
|
45
|
+
* @param {string} path
|
|
46
|
+
* @param {*} value
|
|
47
|
+
* @param {Object} obj
|
|
48
|
+
*/
|
|
49
|
+
export function setProperty(path, value, obj) {
|
|
50
|
+
if (obj && path) {
|
|
51
|
+
path
|
|
52
|
+
.split('.')
|
|
53
|
+
.slice(0, -1)
|
|
54
|
+
.reduce((o, p) => {
|
|
55
|
+
// Create an object
|
|
56
|
+
if (!o[p]) {
|
|
57
|
+
o[p] = {};
|
|
58
|
+
}
|
|
59
|
+
return o[p];
|
|
60
|
+
}, obj);
|
|
61
|
+
|
|
62
|
+
set(obj, path, value);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2000 -
|
|
3
|
+
* Copyright (c) 2000 - 2023 Vaadin Ltd.
|
|
4
4
|
*
|
|
5
5
|
* This program is available under Vaadin Commercial License and Service Terms.
|
|
6
6
|
*
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* See https://vaadin.com/commercial-license-and-service-terms for the full
|
|
9
9
|
* license.
|
|
10
10
|
*/
|
|
11
|
+
import { setProperty } from './vaadin-crud-helpers.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* @polymerMixin
|
|
@@ -46,17 +47,19 @@ export const IncludedMixin = (superClass) =>
|
|
|
46
47
|
/** @private */
|
|
47
48
|
__onExcludeChange(exclude) {
|
|
48
49
|
if (typeof exclude === 'string') {
|
|
49
|
-
this.exclude = exclude ? RegExp(exclude.replace(/, */
|
|
50
|
+
this.exclude = exclude ? RegExp(exclude.replace(/, */gu, '|'), 'iu') : undefined;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
/** @private */
|
|
54
55
|
__onIncludeChange(include) {
|
|
55
56
|
if (typeof include === 'string') {
|
|
56
|
-
this.include = include ? include.split(/, */) : undefined;
|
|
57
|
+
this.include = include ? include.split(/, */u) : undefined;
|
|
57
58
|
} else if (!this._fields && Array.isArray(include)) {
|
|
58
59
|
const item = {};
|
|
59
|
-
this.include.forEach((path) =>
|
|
60
|
+
this.include.forEach((path) => {
|
|
61
|
+
setProperty(path, null, item);
|
|
62
|
+
});
|
|
60
63
|
this._configure(item);
|
|
61
64
|
}
|
|
62
65
|
}
|
package/src/vaadin-crud.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2000 -
|
|
3
|
+
* Copyright (c) 2000 - 2023 Vaadin Ltd.
|
|
4
4
|
*
|
|
5
5
|
* This program is available under Vaadin Commercial License and Service Terms.
|
|
6
6
|
*
|
|
@@ -176,7 +176,8 @@ export type CrudEventMap<T> = CrudCustomEventMap<T> & HTMLElementEventMap;
|
|
|
176
176
|
* `save-button` | To replace the "Save" button.
|
|
177
177
|
* `cancel-button`| To replace the "Cancel" button.
|
|
178
178
|
* `delete-button`| To replace the "Delete" button.
|
|
179
|
-
* `toolbar` | To
|
|
179
|
+
* `toolbar` | To provide the toolbar content (by default, it's empty).
|
|
180
|
+
* `new-button` | To replace the "New item" button.
|
|
180
181
|
*
|
|
181
182
|
* #### Example:
|
|
182
183
|
*
|
|
@@ -193,10 +194,8 @@ export type CrudEventMap<T> = CrudCustomEventMap<T> & HTMLElementEventMap;
|
|
|
193
194
|
* <vaadin-text-field label="Surname" path="surname"></vaadin-text-field>
|
|
194
195
|
* </vaadin-form-layout>
|
|
195
196
|
*
|
|
196
|
-
* <div slot="toolbar">
|
|
197
|
-
*
|
|
198
|
-
* <button new-button>New singer</button>
|
|
199
|
-
* </div>
|
|
197
|
+
* <div slot="toolbar">Total singers: 2</div>
|
|
198
|
+
* <button slot="new-button">New singer</button>
|
|
200
199
|
*
|
|
201
200
|
* <button slot="save-button">Save changes</button>
|
|
202
201
|
* <button slot="cancel-button">Discard changes</button>
|
package/src/vaadin-crud.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* Copyright (c) 2000 -
|
|
3
|
+
* Copyright (c) 2000 - 2023 Vaadin Ltd.
|
|
4
4
|
*
|
|
5
5
|
* This program is available under Vaadin Commercial License and Service Terms.
|
|
6
6
|
*
|
|
@@ -20,8 +20,23 @@ import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|
|
20
20
|
import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
|
|
21
21
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
22
22
|
import { MediaQueryController } from '@vaadin/component-base/src/media-query-controller.js';
|
|
23
|
-
import {
|
|
23
|
+
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
24
24
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
25
|
+
import { getProperty, setProperty } from './vaadin-crud-helpers.js';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @private
|
|
29
|
+
* A to initialize slotted button.
|
|
30
|
+
*/
|
|
31
|
+
class ButtonSlotController extends SlotController {
|
|
32
|
+
constructor(host, type, theme) {
|
|
33
|
+
super(host, `${type}-button`, 'vaadin-button', {
|
|
34
|
+
initializer: (button) => {
|
|
35
|
+
button.setAttribute('theme', theme);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
25
40
|
|
|
26
41
|
/**
|
|
27
42
|
* `<vaadin-crud>` is a Web Component for [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations.
|
|
@@ -79,7 +94,8 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
79
94
|
* `save-button` | To replace the "Save" button.
|
|
80
95
|
* `cancel-button`| To replace the "Cancel" button.
|
|
81
96
|
* `delete-button`| To replace the "Delete" button.
|
|
82
|
-
* `toolbar` | To
|
|
97
|
+
* `toolbar` | To provide the toolbar content (by default, it's empty).
|
|
98
|
+
* `new-button` | To replace the "New item" button.
|
|
83
99
|
*
|
|
84
100
|
* #### Example:
|
|
85
101
|
*
|
|
@@ -96,10 +112,8 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
96
112
|
* <vaadin-text-field label="Surname" path="surname"></vaadin-text-field>
|
|
97
113
|
* </vaadin-form-layout>
|
|
98
114
|
*
|
|
99
|
-
* <div slot="toolbar">
|
|
100
|
-
*
|
|
101
|
-
* <button new-button>New singer</button>
|
|
102
|
-
* </div>
|
|
115
|
+
* <div slot="toolbar">Total singers: 2</div>
|
|
116
|
+
* <button slot="new-button">New singer</button>
|
|
103
117
|
*
|
|
104
118
|
* <button slot="save-button">Save changes</button>
|
|
105
119
|
* <button slot="cancel-button">Discard changes</button>
|
|
@@ -169,10 +183,9 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
169
183
|
* @extends HTMLElement
|
|
170
184
|
* @mixes ControllerMixin
|
|
171
185
|
* @mixes ElementMixin
|
|
172
|
-
* @mixes SlotMixin
|
|
173
186
|
* @mixes ThemableMixin
|
|
174
187
|
*/
|
|
175
|
-
class Crud extends
|
|
188
|
+
class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement))) {
|
|
176
189
|
static get template() {
|
|
177
190
|
return html`
|
|
178
191
|
<style>
|
|
@@ -258,23 +271,11 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
258
271
|
|
|
259
272
|
<div id="container">
|
|
260
273
|
<div id="main">
|
|
261
|
-
<slot name="grid">
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
exclude="[[exclude]]"
|
|
267
|
-
no-sort="[[noSort]]"
|
|
268
|
-
no-filter="[[noFilter]]"
|
|
269
|
-
no-head="[[noHead]]"
|
|
270
|
-
hide-edit-column="[[editOnClick]]"
|
|
271
|
-
></vaadin-crud-grid>
|
|
272
|
-
</slot>
|
|
273
|
-
|
|
274
|
-
<div id="toolbar" part="toolbar" on-click="__new">
|
|
275
|
-
<slot name="toolbar">
|
|
276
|
-
<vaadin-button new-button="" id="new" theme="primary">[[i18n.newItem]]</vaadin-button>
|
|
277
|
-
</slot>
|
|
274
|
+
<slot name="grid"></slot>
|
|
275
|
+
|
|
276
|
+
<div id="toolbar" part="toolbar">
|
|
277
|
+
<slot name="toolbar"></slot>
|
|
278
|
+
<slot name="new-button"></slot>
|
|
278
279
|
</div>
|
|
279
280
|
</div>
|
|
280
281
|
|
|
@@ -308,7 +309,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
308
309
|
theme$="[[_theme]]"
|
|
309
310
|
id="confirmCancel"
|
|
310
311
|
on-confirm="__confirmCancel"
|
|
311
|
-
cancel
|
|
312
|
+
cancel-button-visible
|
|
312
313
|
confirm-text="[[i18n.confirm.cancel.button.confirm]]"
|
|
313
314
|
cancel-text="[[i18n.confirm.cancel.button.dismiss]]"
|
|
314
315
|
header="[[i18n.confirm.cancel.title]]"
|
|
@@ -320,7 +321,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
320
321
|
theme$="[[_theme]]"
|
|
321
322
|
id="confirmDelete"
|
|
322
323
|
on-confirm="__confirmDelete"
|
|
323
|
-
cancel
|
|
324
|
+
cancel-button-visible
|
|
324
325
|
confirm-text="[[i18n.confirm.delete.button.confirm]]"
|
|
325
326
|
cancel-text="[[i18n.confirm.delete.button.dismiss]]"
|
|
326
327
|
header="[[i18n.confirm.delete.title]]"
|
|
@@ -345,7 +346,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
345
346
|
* @private
|
|
346
347
|
*/
|
|
347
348
|
_grid: {
|
|
348
|
-
type:
|
|
349
|
+
type: Object,
|
|
349
350
|
observer: '__gridChanged',
|
|
350
351
|
},
|
|
351
352
|
|
|
@@ -354,7 +355,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
354
355
|
* @private
|
|
355
356
|
*/
|
|
356
357
|
_form: {
|
|
357
|
-
type:
|
|
358
|
+
type: Object,
|
|
358
359
|
observer: '__formChanged',
|
|
359
360
|
},
|
|
360
361
|
|
|
@@ -363,34 +364,39 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
363
364
|
* @private
|
|
364
365
|
*/
|
|
365
366
|
_saveButton: {
|
|
366
|
-
type:
|
|
367
|
-
observer: '__saveButtonChanged',
|
|
367
|
+
type: Object,
|
|
368
368
|
},
|
|
369
369
|
|
|
370
370
|
/**
|
|
371
|
-
* A reference to the
|
|
371
|
+
* A reference to the delete button which will be teleported to the dialog
|
|
372
372
|
* @private
|
|
373
373
|
*/
|
|
374
374
|
_deleteButton: {
|
|
375
|
-
type:
|
|
376
|
-
observer: '__deleteButtonChanged',
|
|
375
|
+
type: Object,
|
|
377
376
|
},
|
|
378
377
|
|
|
379
378
|
/**
|
|
380
|
-
* A reference to the
|
|
379
|
+
* A reference to the cancel button which will be teleported to the dialog
|
|
381
380
|
* @private
|
|
382
381
|
*/
|
|
383
382
|
_cancelButton: {
|
|
384
|
-
type:
|
|
385
|
-
observer: '__cancelButtonChanged',
|
|
383
|
+
type: Object,
|
|
386
384
|
},
|
|
387
385
|
|
|
388
386
|
/**
|
|
389
|
-
* A reference to the editor header element
|
|
387
|
+
* A reference to the default editor header element created by the CRUD
|
|
390
388
|
* @private
|
|
391
389
|
*/
|
|
392
|
-
|
|
393
|
-
type:
|
|
390
|
+
_defaultHeader: {
|
|
391
|
+
type: Object,
|
|
392
|
+
},
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* A reference to the "New item" button
|
|
396
|
+
* @private
|
|
397
|
+
*/
|
|
398
|
+
_newButton: {
|
|
399
|
+
type: Object,
|
|
394
400
|
},
|
|
395
401
|
|
|
396
402
|
/**
|
|
@@ -629,13 +635,15 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
629
635
|
|
|
630
636
|
static get observers() {
|
|
631
637
|
return [
|
|
632
|
-
'__headerPropsChanged(
|
|
638
|
+
'__headerPropsChanged(_defaultHeader, __isNew, i18n.newItem, i18n.editItem)',
|
|
633
639
|
'__formPropsChanged(_form, _theme, include, exclude)',
|
|
640
|
+
'__gridPropsChanged(_grid, _theme, include, exclude, noFilter, noHead, noSort)',
|
|
634
641
|
'__i18nChanged(i18n, _grid)',
|
|
635
642
|
'__editOnClickChanged(editOnClick, _grid)',
|
|
636
643
|
'__saveButtonPropsChanged(_saveButton, i18n.saveItem, __isDirty)',
|
|
637
644
|
'__cancelButtonPropsChanged(_cancelButton, i18n.cancel)',
|
|
638
645
|
'__deleteButtonPropsChanged(_deleteButton, i18n.deleteItem, __isNew)',
|
|
646
|
+
'__newButtonPropsChanged(_newButton, i18n.newItem)',
|
|
639
647
|
];
|
|
640
648
|
}
|
|
641
649
|
|
|
@@ -644,59 +652,66 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
644
652
|
return ['bottom', 'aside'].includes(editorPosition);
|
|
645
653
|
}
|
|
646
654
|
|
|
647
|
-
/** @protected */
|
|
648
|
-
get slots() {
|
|
649
|
-
// NOTE: order in which the toolbar buttons are listed matters.
|
|
650
|
-
return {
|
|
651
|
-
...super.slots,
|
|
652
|
-
header: () => {
|
|
653
|
-
return document.createElement('h3');
|
|
654
|
-
},
|
|
655
|
-
form: () => {
|
|
656
|
-
return document.createElement('vaadin-crud-form');
|
|
657
|
-
},
|
|
658
|
-
'save-button': () => {
|
|
659
|
-
const button = document.createElement('vaadin-button');
|
|
660
|
-
button.id = 'save';
|
|
661
|
-
button.setAttribute('theme', 'primary');
|
|
662
|
-
return button;
|
|
663
|
-
},
|
|
664
|
-
'cancel-button': () => {
|
|
665
|
-
const button = document.createElement('vaadin-button');
|
|
666
|
-
button.id = 'cancel';
|
|
667
|
-
button.setAttribute('theme', 'tertiary');
|
|
668
|
-
return button;
|
|
669
|
-
},
|
|
670
|
-
'delete-button': () => {
|
|
671
|
-
const button = document.createElement('vaadin-button');
|
|
672
|
-
button.id = 'delete';
|
|
673
|
-
button.setAttribute('theme', 'tertiary error');
|
|
674
|
-
return button;
|
|
675
|
-
},
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
|
|
679
655
|
constructor() {
|
|
680
656
|
super();
|
|
657
|
+
|
|
658
|
+
this.__cancel = this.__cancel.bind(this);
|
|
659
|
+
this.__delete = this.__delete.bind(this);
|
|
660
|
+
this.__save = this.__save.bind(this);
|
|
661
|
+
this.__new = this.__new.bind(this);
|
|
662
|
+
this.__onFormChange = this.__onFormChange.bind(this);
|
|
663
|
+
this.__onGridEdit = this.__onGridEdit.bind(this);
|
|
664
|
+
this.__onGridSizeChanged = this.__onGridSizeChanged.bind(this);
|
|
665
|
+
this.__onGridActiveItemChanged = this.__onGridActiveItemChanged.bind(this);
|
|
666
|
+
|
|
681
667
|
this._observer = new FlattenedNodesObserver(this, (info) => {
|
|
682
668
|
this.__onDomChange(info.addedNodes);
|
|
683
669
|
});
|
|
684
670
|
}
|
|
685
671
|
|
|
672
|
+
/** @protected */
|
|
673
|
+
get _headerNode() {
|
|
674
|
+
return this._headerController && this._headerController.node;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* A reference to all fields inside the [`_form`](#/elements/vaadin-crud#property-_form) element
|
|
679
|
+
* @return {!Array<!HTMLElement>}
|
|
680
|
+
* @protected
|
|
681
|
+
*/
|
|
682
|
+
get _fields() {
|
|
683
|
+
if (!this.__fields || !this.__fields.length) {
|
|
684
|
+
this.__fields = Array.from(this._form.querySelectorAll('*')).filter((e) => e.validate || e.checkValidity);
|
|
685
|
+
}
|
|
686
|
+
return this.__fields;
|
|
687
|
+
}
|
|
688
|
+
|
|
686
689
|
/** @protected */
|
|
687
690
|
ready() {
|
|
688
691
|
super.ready();
|
|
689
|
-
|
|
690
|
-
this.__cancel = this.__cancel.bind(this);
|
|
691
|
-
this.__delete = this.__delete.bind(this);
|
|
692
|
-
this.__onFormChange = this.__onFormChange.bind(this);
|
|
693
|
-
this.__onGridEdit = this.__onGridEdit.bind(this);
|
|
694
|
-
this.__onGridSizeChanged = this.__onGridSizeChanged.bind(this);
|
|
695
|
-
this.__onGridActiveItemChanged = this.__onGridActiveItemChanged.bind(this);
|
|
696
|
-
this._grid = this.$.grid;
|
|
692
|
+
|
|
697
693
|
this.$.dialog.$.overlay.addEventListener('vaadin-overlay-outside-click', this.__cancel);
|
|
698
694
|
this.$.dialog.$.overlay.addEventListener('vaadin-overlay-escape-press', this.__cancel);
|
|
699
695
|
|
|
696
|
+
this._headerController = new SlotController(this, 'header', 'h3', {
|
|
697
|
+
initializer: (node) => {
|
|
698
|
+
this._defaultHeader = node;
|
|
699
|
+
},
|
|
700
|
+
});
|
|
701
|
+
this.addController(this._headerController);
|
|
702
|
+
|
|
703
|
+
this._gridController = new SlotController(this, 'grid', 'vaadin-crud-grid');
|
|
704
|
+
this.addController(this._gridController);
|
|
705
|
+
|
|
706
|
+
this.addController(new SlotController(this, 'form', 'vaadin-crud-form'));
|
|
707
|
+
|
|
708
|
+
this.addController(new ButtonSlotController(this, 'new', 'primary'));
|
|
709
|
+
|
|
710
|
+
// NOTE: order in which buttons are added should match the order of slots in template
|
|
711
|
+
this.addController(new ButtonSlotController(this, 'save', 'primary'));
|
|
712
|
+
this.addController(new ButtonSlotController(this, 'cancel', 'tertiary'));
|
|
713
|
+
this.addController(new ButtonSlotController(this, 'delete', 'tertiary error'));
|
|
714
|
+
|
|
700
715
|
this.addController(
|
|
701
716
|
new MediaQueryController(this._fullscreenMediaQuery, (matches) => {
|
|
702
717
|
this._fullscreen = matches;
|
|
@@ -849,7 +864,8 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
849
864
|
/** @private */
|
|
850
865
|
__onDomChange(addedNodes) {
|
|
851
866
|
// TODO: restore default button when a corresponding slotted button is removed.
|
|
852
|
-
//
|
|
867
|
+
// This would require us to detect where to insert a button after teleporting it,
|
|
868
|
+
// which happens after opening a dialog and closing it (default editor position).
|
|
853
869
|
addedNodes
|
|
854
870
|
.filter((node) => node.nodeType === Node.ELEMENT_NODE)
|
|
855
871
|
.forEach((node) => {
|
|
@@ -867,9 +883,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
867
883
|
this._form = node;
|
|
868
884
|
} else if (slotAttributeValue.indexOf('button') >= 0) {
|
|
869
885
|
const [button] = slotAttributeValue.split('-');
|
|
870
|
-
this
|
|
871
|
-
} else if (slotAttributeValue === 'header') {
|
|
872
|
-
this._headerNode = node;
|
|
886
|
+
this.__setupSlottedButton(button, node);
|
|
873
887
|
}
|
|
874
888
|
});
|
|
875
889
|
|
|
@@ -963,12 +977,27 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
963
977
|
}
|
|
964
978
|
|
|
965
979
|
/**
|
|
966
|
-
* @param {HTMLElement}
|
|
967
|
-
* @param {
|
|
980
|
+
* @param {HTMLElement | undefined} form
|
|
981
|
+
* @param {string} theme
|
|
982
|
+
* @param {string | string[] | undefined} include
|
|
983
|
+
* @param {string | RegExp} exclude
|
|
968
984
|
* @private
|
|
969
985
|
*/
|
|
970
|
-
|
|
971
|
-
|
|
986
|
+
// eslint-disable-next-line max-params
|
|
987
|
+
__gridPropsChanged(grid, theme, include, exclude, noFilter, noHead, noSort) {
|
|
988
|
+
if (grid && grid === this._gridController.defaultNode) {
|
|
989
|
+
grid.include = include;
|
|
990
|
+
grid.exclude = exclude;
|
|
991
|
+
grid.noFilter = noFilter;
|
|
992
|
+
grid.noHead = noHead;
|
|
993
|
+
grid.noSort = noSort;
|
|
994
|
+
|
|
995
|
+
if (theme) {
|
|
996
|
+
grid.setAttribute('theme', theme);
|
|
997
|
+
} else {
|
|
998
|
+
grid.removeAttribute('theme');
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
972
1001
|
}
|
|
973
1002
|
|
|
974
1003
|
/**
|
|
@@ -984,15 +1013,6 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
984
1013
|
}
|
|
985
1014
|
}
|
|
986
1015
|
|
|
987
|
-
/**
|
|
988
|
-
* @param {HTMLElement} deleteButton
|
|
989
|
-
* @param {HTMLElement | undefined} oldDeleteButton
|
|
990
|
-
* @private
|
|
991
|
-
*/
|
|
992
|
-
__deleteButtonChanged(deleteButton, oldDeleteButton) {
|
|
993
|
-
this.__setupSlottedButton(deleteButton, oldDeleteButton, this.__delete);
|
|
994
|
-
}
|
|
995
|
-
|
|
996
1016
|
/**
|
|
997
1017
|
* @param {HTMLElement | undefined} deleteButton
|
|
998
1018
|
* @param {string} i18nLabel
|
|
@@ -1006,15 +1026,6 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
1006
1026
|
}
|
|
1007
1027
|
}
|
|
1008
1028
|
|
|
1009
|
-
/**
|
|
1010
|
-
* @param {HTMLElement} cancelButton
|
|
1011
|
-
* @param {HTMLElement | undefined} oldCancelButton
|
|
1012
|
-
* @private
|
|
1013
|
-
*/
|
|
1014
|
-
__cancelButtonChanged(cancelButton, oldCancelButton) {
|
|
1015
|
-
this.__setupSlottedButton(cancelButton, oldCancelButton, this.__cancel);
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
1029
|
/**
|
|
1019
1030
|
* @param {HTMLElement | undefined} saveButton
|
|
1020
1031
|
* @param {string} i18nLabel
|
|
@@ -1027,17 +1038,31 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
1027
1038
|
}
|
|
1028
1039
|
|
|
1029
1040
|
/**
|
|
1041
|
+
* @param {HTMLElement | undefined} newButton
|
|
1042
|
+
* @param {string} i18nNewItem
|
|
1043
|
+
* @private
|
|
1044
|
+
*/
|
|
1045
|
+
__newButtonPropsChanged(newButton, i18nNewItem) {
|
|
1046
|
+
if (newButton) {
|
|
1047
|
+
newButton.textContent = i18nNewItem;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* @param {string} type
|
|
1030
1053
|
* @param {HTMLElement} newButton
|
|
1031
|
-
* @param {HTMLElement | undefined | null} oldButton
|
|
1032
|
-
* @param {Function} clickListener
|
|
1033
1054
|
* @private
|
|
1034
1055
|
*/
|
|
1035
|
-
__setupSlottedButton(
|
|
1036
|
-
|
|
1037
|
-
|
|
1056
|
+
__setupSlottedButton(type, button) {
|
|
1057
|
+
const property = `_${type}Button`;
|
|
1058
|
+
const listener = `__${type}`;
|
|
1059
|
+
|
|
1060
|
+
if (this[property] && this[property] !== button) {
|
|
1061
|
+
this[property].remove();
|
|
1038
1062
|
}
|
|
1039
1063
|
|
|
1040
|
-
|
|
1064
|
+
button.addEventListener('click', this[listener]);
|
|
1065
|
+
this[property] = button;
|
|
1041
1066
|
}
|
|
1042
1067
|
|
|
1043
1068
|
/** @private */
|
|
@@ -1048,15 +1073,17 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
1048
1073
|
}
|
|
1049
1074
|
|
|
1050
1075
|
/** @private */
|
|
1051
|
-
__editOnClickChanged(editOnClick,
|
|
1052
|
-
if (!
|
|
1076
|
+
__editOnClickChanged(editOnClick, grid) {
|
|
1077
|
+
if (!grid) {
|
|
1053
1078
|
return;
|
|
1054
1079
|
}
|
|
1055
1080
|
|
|
1081
|
+
grid.hideEditColumn = editOnClick;
|
|
1082
|
+
|
|
1056
1083
|
if (editOnClick) {
|
|
1057
|
-
|
|
1084
|
+
grid.addEventListener('active-item-changed', this.__onGridActiveItemChanged);
|
|
1058
1085
|
} else {
|
|
1059
|
-
|
|
1086
|
+
grid.removeEventListener('active-item-changed', this.__onGridActiveItemChanged);
|
|
1060
1087
|
}
|
|
1061
1088
|
}
|
|
1062
1089
|
|
|
@@ -1157,7 +1184,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
1157
1184
|
this._fields.forEach((e) => {
|
|
1158
1185
|
const path = e.path || e.getAttribute('path');
|
|
1159
1186
|
if (path) {
|
|
1160
|
-
e.value =
|
|
1187
|
+
e.value = getProperty(path, item);
|
|
1161
1188
|
}
|
|
1162
1189
|
});
|
|
1163
1190
|
|
|
@@ -1166,18 +1193,6 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
1166
1193
|
}
|
|
1167
1194
|
}
|
|
1168
1195
|
|
|
1169
|
-
/**
|
|
1170
|
-
* A reference to all fields inside the [`_form`](#/elements/vaadin-crud#property-_form) element
|
|
1171
|
-
* @return {!Array<!HTMLElement>}
|
|
1172
|
-
* @protected
|
|
1173
|
-
*/
|
|
1174
|
-
get _fields() {
|
|
1175
|
-
if (!this.__fields || !this.__fields.length) {
|
|
1176
|
-
this.__fields = Array.from(this._form.querySelectorAll('*')).filter((e) => e.validate || e.checkValidity);
|
|
1177
|
-
}
|
|
1178
|
-
return this.__fields;
|
|
1179
|
-
}
|
|
1180
|
-
|
|
1181
1196
|
/** @private */
|
|
1182
1197
|
__validate() {
|
|
1183
1198
|
return this._fields.every((e) => (e.validate || e.checkValidity).call(e));
|
|
@@ -1185,7 +1200,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
1185
1200
|
|
|
1186
1201
|
/** @private */
|
|
1187
1202
|
__setHighlightedItem(item) {
|
|
1188
|
-
if (this._grid === this
|
|
1203
|
+
if (this._grid === this._gridController.defaultNode) {
|
|
1189
1204
|
this._grid.selectedItems = item ? [item] : [];
|
|
1190
1205
|
}
|
|
1191
1206
|
}
|
|
@@ -1201,11 +1216,8 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
1201
1216
|
}
|
|
1202
1217
|
|
|
1203
1218
|
/** @private */
|
|
1204
|
-
__new(
|
|
1205
|
-
|
|
1206
|
-
if (event.composedPath().some((e) => e.nodeType === 1 && e.hasAttribute('new-button'))) {
|
|
1207
|
-
this.__confirmBeforeChangingEditedItem(null, true);
|
|
1208
|
-
}
|
|
1219
|
+
__new() {
|
|
1220
|
+
this.__confirmBeforeChangingEditedItem(null, true);
|
|
1209
1221
|
}
|
|
1210
1222
|
|
|
1211
1223
|
/** @private */
|
|
@@ -1241,7 +1253,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
1241
1253
|
this._fields.forEach((e) => {
|
|
1242
1254
|
const path = e.path || e.getAttribute('path');
|
|
1243
1255
|
if (path) {
|
|
1244
|
-
|
|
1256
|
+
setProperty(path, e.value, item);
|
|
1245
1257
|
}
|
|
1246
1258
|
});
|
|
1247
1259
|
const evt = this.dispatchEvent(new CustomEvent('save', { detail: { item }, cancelable: true }));
|
|
@@ -1253,7 +1265,9 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
1253
1265
|
this.items.push(item);
|
|
1254
1266
|
}
|
|
1255
1267
|
} else {
|
|
1256
|
-
|
|
1268
|
+
if (!this.editedItem) {
|
|
1269
|
+
this.editedItem = {};
|
|
1270
|
+
}
|
|
1257
1271
|
Object.assign(this.editedItem, item);
|
|
1258
1272
|
}
|
|
1259
1273
|
this._grid.clearCache();
|
|
@@ -1295,23 +1309,6 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
|
|
|
1295
1309
|
}
|
|
1296
1310
|
}
|
|
1297
1311
|
|
|
1298
|
-
/**
|
|
1299
|
-
* Utility method for setting nested values in JSON objects but initializing empty keys unless `Polymer.Base.set`
|
|
1300
|
-
* @private
|
|
1301
|
-
*/
|
|
1302
|
-
__set(path, val, obj) {
|
|
1303
|
-
if (obj && path) {
|
|
1304
|
-
path
|
|
1305
|
-
.split('.')
|
|
1306
|
-
.slice(0, -1)
|
|
1307
|
-
.reduce((o, p) => {
|
|
1308
|
-
o[p] = o[p] || {};
|
|
1309
|
-
return o[p];
|
|
1310
|
-
}, obj);
|
|
1311
|
-
this.set(path, val, obj);
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
1312
|
/**
|
|
1316
1313
|
* Fired when user wants to edit an existing item. If the default is prevented, then
|
|
1317
1314
|
* a new item is not assigned to the form, giving that responsibility to the app, though
|
|
@@ -97,13 +97,6 @@ registerStyles(
|
|
|
97
97
|
:host([dir='rtl']) [part='toolbar'] ::slotted(*:not(:first-child)) {
|
|
98
98
|
margin-right: 0.5em;
|
|
99
99
|
}
|
|
100
|
-
|
|
101
|
-
vaadin-text-field[theme~='small'] {
|
|
102
|
-
height: 24px;
|
|
103
|
-
font-size: var(--material-small-font-size);
|
|
104
|
-
margin: 0;
|
|
105
|
-
padding: 0;
|
|
106
|
-
}
|
|
107
100
|
`,
|
|
108
101
|
],
|
|
109
102
|
{ moduleId: 'material-crud' },
|
package/web-types.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/crud",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "24.0.0-alpha10",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
@@ -295,7 +295,7 @@
|
|
|
295
295
|
},
|
|
296
296
|
{
|
|
297
297
|
"name": "vaadin-crud",
|
|
298
|
-
"description": "`<vaadin-crud>` is a Web Component for [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations.\n\n### Quick Start\n\nAssign an array to the [`items`](https://cdn.vaadin.com/vaadin-web-components/
|
|
298
|
+
"description": "`<vaadin-crud>` is a Web Component for [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations.\n\n### Quick Start\n\nAssign an array to the [`items`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud#property-items) property.\n\nA grid and an editor will be automatically generated and configured based on the data structure provided.\n\n```html\n<vaadin-crud></vaadin-crud>\n```\n```js\nconst crud = document.querySelector('vaadin-crud');\n\ncrud.items = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n```\n\n### Data Provider Function\n\nOtherwise, you can provide a [`dataProvider`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud#property-dataProvider) function.\n\n```js\nconst crud = document.querySelector('vaadin-crud');\n\nconst users = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n\ncrud.dataProvider = (params, callback) => {\n const chunk = users.slice(params.page * params.pageSize, params.page * params.pageSize + params.pageSize);\n callback(chunk, people.length);\n};\n```\n\nNOTE: The auto-generated editor only supports string types. If you need to handle special cases\ncustomizing the editor is discussed below.\n\n### Customization\n\nAlternatively you can fully configure the component by using `slot` names.\n\nSlot name | Description\n---------------|----------------\n`grid` | To replace the auto-generated grid with a custom one.\n`form` | To replace the auto-generated form.\n`save-button` | To replace the \"Save\" button.\n`cancel-button`| To replace the \"Cancel\" button.\n`delete-button`| To replace the \"Delete\" button.\n`toolbar` | To provide the toolbar content (by default, it's empty).\n`new-button` | To replace the \"New item\" button.\n\n#### Example:\n\n```html\n<vaadin-crud id=\"crud\">\n <vaadin-grid slot=\"grid\">\n <vaadin-crud-edit-column></vaadin-crud-edit-column>\n <vaadin-grid-column id=\"column1\"></vaadin-grid-column>\n <vaadin-grid-column id=\"column2\"></vaadin-grid-column>\n </vaadin-grid>\n\n <vaadin-form-layout slot=\"form\">\n <vaadin-text-field label=\"First\" path=\"name\"></vaadin-text-field>\n <vaadin-text-field label=\"Surname\" path=\"surname\"></vaadin-text-field>\n </vaadin-form-layout>\n\n <div slot=\"toolbar\">Total singers: 2</div>\n <button slot=\"new-button\">New singer</button>\n\n <button slot=\"save-button\">Save changes</button>\n <button slot=\"cancel-button\">Discard changes</button>\n <button slot=\"delete-button\">Delete singer</button>\n</vaadin-crud>\n```\n```js\nconst crud = document.querySelector('#crud');\n\nconst column1 = document.querySelector('#column1');\ncolumn1.headerRenderer = (root, column) => {\n root.textContent = 'Name';\n};\ncolumn1.renderer = (root, column, model) => {\n root.textContent = model.item.name;\n};\n\nconst column2 = document.querySelector('#column2');\ncolumn2.headerRenderer = (root, column) => {\n root.textContent = 'Surname';\n};\ncolumn2.renderer = (root, column, model) => {\n root.textContent = model.item.surname;\n};\n\ncrud.items = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n```\n\n### Helpers\n\nThe following elements are used to auto-configure the grid and the editor\n- [`<vaadin-crud-edit-column>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud-edit-column)\n- `<vaadin-crud-grid>` - can be replaced with custom [`<vaadin-grid>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-grid)\n- `<vaadin-crud-form>` - can be replaced with custom [`<vaadin-form-layout>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-form-layout)\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n----------------|----------------\n`toolbar` | Toolbar container at the bottom. By default it contains the the `new` button\n\nThe following custom properties are available:\n\nCustom Property | Description | Default\n----------------|----------------\n--vaadin-crud-editor-max-height | max height of editor when opened on the bottom | 40%\n--vaadin-crud-editor-max-width | max width of editor when opened on the side | 40%\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
|
|
299
299
|
"attributes": [
|
|
300
300
|
{
|
|
301
301
|
"name": "editor-position",
|
|
@@ -350,7 +350,7 @@
|
|
|
350
350
|
},
|
|
351
351
|
{
|
|
352
352
|
"name": "include",
|
|
353
|
-
"description": "A comma-separated list of fields to include in the generated grid and the generated editor.\n\nIt can be used to explicitly define the field order.\n\nWhen it is defined [`exclude`](https://cdn.vaadin.com/vaadin-web-components/
|
|
353
|
+
"description": "A comma-separated list of fields to include in the generated grid and the generated editor.\n\nIt can be used to explicitly define the field order.\n\nWhen it is defined [`exclude`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
|
|
354
354
|
"value": {
|
|
355
355
|
"type": [
|
|
356
356
|
"string",
|
|
@@ -361,7 +361,7 @@
|
|
|
361
361
|
},
|
|
362
362
|
{
|
|
363
363
|
"name": "exclude",
|
|
364
|
-
"description": "A comma-separated list of fields to be excluded from the generated grid and the generated editor.\n\nWhen [`include`](https://cdn.vaadin.com/vaadin-web-components/
|
|
364
|
+
"description": "A comma-separated list of fields to be excluded from the generated grid and the generated editor.\n\nWhen [`include`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
|
|
365
365
|
"value": {
|
|
366
366
|
"type": [
|
|
367
367
|
"string",
|
|
@@ -488,7 +488,7 @@
|
|
|
488
488
|
},
|
|
489
489
|
{
|
|
490
490
|
"name": "include",
|
|
491
|
-
"description": "A comma-separated list of fields to include in the generated grid and the generated editor.\n\nIt can be used to explicitly define the field order.\n\nWhen it is defined [`exclude`](https://cdn.vaadin.com/vaadin-web-components/
|
|
491
|
+
"description": "A comma-separated list of fields to include in the generated grid and the generated editor.\n\nIt can be used to explicitly define the field order.\n\nWhen it is defined [`exclude`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
|
|
492
492
|
"value": {
|
|
493
493
|
"type": [
|
|
494
494
|
"string",
|
|
@@ -499,7 +499,7 @@
|
|
|
499
499
|
},
|
|
500
500
|
{
|
|
501
501
|
"name": "exclude",
|
|
502
|
-
"description": "A comma-separated list of fields to be excluded from the generated grid and the generated editor.\n\nWhen [`include`](https://cdn.vaadin.com/vaadin-web-components/
|
|
502
|
+
"description": "A comma-separated list of fields to be excluded from the generated grid and the generated editor.\n\nWhen [`include`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
|
|
503
503
|
"value": {
|
|
504
504
|
"type": [
|
|
505
505
|
"string",
|
package/web-types.lit.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/crud",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "24.0.0-alpha10",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"framework": "lit",
|
|
7
7
|
"framework-config": {
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
},
|
|
122
122
|
{
|
|
123
123
|
"name": "vaadin-crud",
|
|
124
|
-
"description": "`<vaadin-crud>` is a Web Component for [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations.\n\n### Quick Start\n\nAssign an array to the [`items`](https://cdn.vaadin.com/vaadin-web-components/
|
|
124
|
+
"description": "`<vaadin-crud>` is a Web Component for [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations.\n\n### Quick Start\n\nAssign an array to the [`items`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud#property-items) property.\n\nA grid and an editor will be automatically generated and configured based on the data structure provided.\n\n```html\n<vaadin-crud></vaadin-crud>\n```\n```js\nconst crud = document.querySelector('vaadin-crud');\n\ncrud.items = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n```\n\n### Data Provider Function\n\nOtherwise, you can provide a [`dataProvider`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud#property-dataProvider) function.\n\n```js\nconst crud = document.querySelector('vaadin-crud');\n\nconst users = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n\ncrud.dataProvider = (params, callback) => {\n const chunk = users.slice(params.page * params.pageSize, params.page * params.pageSize + params.pageSize);\n callback(chunk, people.length);\n};\n```\n\nNOTE: The auto-generated editor only supports string types. If you need to handle special cases\ncustomizing the editor is discussed below.\n\n### Customization\n\nAlternatively you can fully configure the component by using `slot` names.\n\nSlot name | Description\n---------------|----------------\n`grid` | To replace the auto-generated grid with a custom one.\n`form` | To replace the auto-generated form.\n`save-button` | To replace the \"Save\" button.\n`cancel-button`| To replace the \"Cancel\" button.\n`delete-button`| To replace the \"Delete\" button.\n`toolbar` | To provide the toolbar content (by default, it's empty).\n`new-button` | To replace the \"New item\" button.\n\n#### Example:\n\n```html\n<vaadin-crud id=\"crud\">\n <vaadin-grid slot=\"grid\">\n <vaadin-crud-edit-column></vaadin-crud-edit-column>\n <vaadin-grid-column id=\"column1\"></vaadin-grid-column>\n <vaadin-grid-column id=\"column2\"></vaadin-grid-column>\n </vaadin-grid>\n\n <vaadin-form-layout slot=\"form\">\n <vaadin-text-field label=\"First\" path=\"name\"></vaadin-text-field>\n <vaadin-text-field label=\"Surname\" path=\"surname\"></vaadin-text-field>\n </vaadin-form-layout>\n\n <div slot=\"toolbar\">Total singers: 2</div>\n <button slot=\"new-button\">New singer</button>\n\n <button slot=\"save-button\">Save changes</button>\n <button slot=\"cancel-button\">Discard changes</button>\n <button slot=\"delete-button\">Delete singer</button>\n</vaadin-crud>\n```\n```js\nconst crud = document.querySelector('#crud');\n\nconst column1 = document.querySelector('#column1');\ncolumn1.headerRenderer = (root, column) => {\n root.textContent = 'Name';\n};\ncolumn1.renderer = (root, column, model) => {\n root.textContent = model.item.name;\n};\n\nconst column2 = document.querySelector('#column2');\ncolumn2.headerRenderer = (root, column) => {\n root.textContent = 'Surname';\n};\ncolumn2.renderer = (root, column, model) => {\n root.textContent = model.item.surname;\n};\n\ncrud.items = [\n { name: 'John', surname: 'Lennon', role: 'singer' },\n { name: 'Ringo', surname: 'Starr', role: 'drums' },\n // ... more items\n];\n```\n\n### Helpers\n\nThe following elements are used to auto-configure the grid and the editor\n- [`<vaadin-crud-edit-column>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud-edit-column)\n- `<vaadin-crud-grid>` - can be replaced with custom [`<vaadin-grid>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-grid)\n- `<vaadin-crud-form>` - can be replaced with custom [`<vaadin-form-layout>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-form-layout)\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n----------------|----------------\n`toolbar` | Toolbar container at the bottom. By default it contains the the `new` button\n\nThe following custom properties are available:\n\nCustom Property | Description | Default\n----------------|----------------\n--vaadin-crud-editor-max-height | max height of editor when opened on the bottom | 40%\n--vaadin-crud-editor-max-width | max width of editor when opened on the side | 40%\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
|
|
125
125
|
"extension": true,
|
|
126
126
|
"attributes": [
|
|
127
127
|
{
|
|
@@ -196,14 +196,14 @@
|
|
|
196
196
|
},
|
|
197
197
|
{
|
|
198
198
|
"name": ".include",
|
|
199
|
-
"description": "A comma-separated list of fields to include in the generated grid and the generated editor.\n\nIt can be used to explicitly define the field order.\n\nWhen it is defined [`exclude`](https://cdn.vaadin.com/vaadin-web-components/
|
|
199
|
+
"description": "A comma-separated list of fields to include in the generated grid and the generated editor.\n\nIt can be used to explicitly define the field order.\n\nWhen it is defined [`exclude`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud#property-exclude) is ignored.\n\nDefault is undefined meaning that all properties in the object should be mapped to fields.",
|
|
200
200
|
"value": {
|
|
201
201
|
"kind": "expression"
|
|
202
202
|
}
|
|
203
203
|
},
|
|
204
204
|
{
|
|
205
205
|
"name": ".exclude",
|
|
206
|
-
"description": "A comma-separated list of fields to be excluded from the generated grid and the generated editor.\n\nWhen [`include`](https://cdn.vaadin.com/vaadin-web-components/
|
|
206
|
+
"description": "A comma-separated list of fields to be excluded from the generated grid and the generated editor.\n\nWhen [`include`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha10/#/elements/vaadin-crud#property-include) is defined, this parameter is ignored.\n\nDefault is to exclude all private fields (those properties starting with underscore)",
|
|
207
207
|
"value": {
|
|
208
208
|
"kind": "expression"
|
|
209
209
|
}
|