@vaadin/crud 24.0.0-alpha1 → 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.
@@ -1,7 +1,12 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2018 - 2022 Vaadin Ltd.
4
- * This program is available under Commercial Vaadin Developer License 4.0, available at https://vaadin.com/license/cvdl-4.0.
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.
5
10
  */
6
11
  import '@vaadin/button/src/vaadin-button.js';
7
12
  import '@vaadin/dialog/src/vaadin-dialog.js';
@@ -15,8 +20,23 @@ import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
15
20
  import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
16
21
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
17
22
  import { MediaQueryController } from '@vaadin/component-base/src/media-query-controller.js';
18
- import { SlotMixin } from '@vaadin/component-base/src/slot-mixin.js';
23
+ import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
19
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
+ }
20
40
 
21
41
  /**
22
42
  * `<vaadin-crud>` is a Web Component for [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations.
@@ -27,23 +47,34 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
27
47
  *
28
48
  * A grid and an editor will be automatically generated and configured based on the data structure provided.
29
49
  *
30
- * #### Example:
31
50
  * ```html
32
- * <vaadin-crud items='[{"name": "John", "surname": "Lennon", "role": "singer"},
33
- * {"name": "Ringo", "surname": "Starr", "role": "drums"}]'></vaadin-crud>
51
+ * <vaadin-crud></vaadin-crud>
52
+ * ```
53
+ *
54
+ * ```js
55
+ * const crud = document.querySelector('vaadin-crud');
56
+ *
57
+ * crud.items = [
58
+ * { name: 'John', surname: 'Lennon', role: 'singer' },
59
+ * { name: 'Ringo', surname: 'Starr', role: 'drums' },
60
+ * // ... more items
61
+ * ];
34
62
  * ```
35
63
  *
36
64
  * ### Data Provider Function
37
65
  *
38
66
  * Otherwise, you can provide a [`dataProvider`](#/elements/vaadin-crud#property-dataProvider) function.
39
- * #### Example:
40
- * ```html
41
- * <vaadin-crud></vaadin-crud>
42
- * ```
67
+ *
43
68
  * ```js
44
69
  * const crud = document.querySelector('vaadin-crud');
45
- * const users = [{'name': 'John', 'surname': 'Lennon', 'role': 'singer'}, ...];
46
- * crud.dataProvider = function(params, callback) {
70
+ *
71
+ * const users = [
72
+ * { name: 'John', surname: 'Lennon', role: 'singer' },
73
+ * { name: 'Ringo', surname: 'Starr', role: 'drums' },
74
+ * // ... more items
75
+ * ];
76
+ *
77
+ * crud.dataProvider = (params, callback) => {
47
78
  * const chunk = users.slice(params.page * params.pageSize, params.page * params.pageSize + params.pageSize);
48
79
  * callback(chunk, people.length);
49
80
  * };
@@ -56,20 +87,20 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
56
87
  *
57
88
  * Alternatively you can fully configure the component by using `slot` names.
58
89
  *
59
- * Slot name | Description
60
- * ----------------|----------------
61
- * `grid` | To replace the auto-generated grid with a custom one.
62
- * `form` | To replace the auto-generated form.
63
- * `toolbar` | To replace the toolbar content. Add an element with the attribute `new-button` for the new item action.
90
+ * Slot name | Description
91
+ * ---------------|----------------
92
+ * `grid` | To replace the auto-generated grid with a custom one.
93
+ * `form` | To replace the auto-generated form.
94
+ * `save-button` | To replace the "Save" button.
95
+ * `cancel-button`| To replace the "Cancel" button.
96
+ * `delete-button`| To replace the "Delete" button.
97
+ * `toolbar` | To provide the toolbar content (by default, it's empty).
98
+ * `new-button` | To replace the "New item" button.
64
99
  *
65
100
  * #### Example:
66
101
  *
67
102
  * ```html
68
- * <vaadin-crud
69
- * id="crud"
70
- * items='[{"name": "John", "surname": "Lennon", "role": "singer"},
71
- * {"name": "Ringo", "surname": "Starr", "role": "drums"}]'
72
- * >
103
+ * <vaadin-crud id="crud">
73
104
  * <vaadin-grid slot="grid">
74
105
  * <vaadin-crud-edit-column></vaadin-crud-edit-column>
75
106
  * <vaadin-grid-column id="column1"></vaadin-grid-column>
@@ -81,10 +112,12 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
81
112
  * <vaadin-text-field label="Surname" path="surname"></vaadin-text-field>
82
113
  * </vaadin-form-layout>
83
114
  *
84
- * <div slot="toolbar">
85
- * Total singers: [[size]]
86
- * <button new-button>New singer</button>
87
- * </div>
115
+ * <div slot="toolbar">Total singers: 2</div>
116
+ * <button slot="new-button">New singer</button>
117
+ *
118
+ * <button slot="save-button">Save changes</button>
119
+ * <button slot="cancel-button">Discard changes</button>
120
+ * <button slot="delete-button">Delete singer</button>
88
121
  * </vaadin-crud>
89
122
  * ```
90
123
  * ```js
@@ -105,6 +138,12 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
105
138
  * column2.renderer = (root, column, model) => {
106
139
  * root.textContent = model.item.surname;
107
140
  * };
141
+ *
142
+ * crud.items = [
143
+ * { name: 'John', surname: 'Lennon', role: 'singer' },
144
+ * { name: 'Ringo', surname: 'Starr', role: 'drums' },
145
+ * // ... more items
146
+ * ];
108
147
  * ```
109
148
  *
110
149
  * ### Helpers
@@ -144,10 +183,9 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
144
183
  * @extends HTMLElement
145
184
  * @mixes ControllerMixin
146
185
  * @mixes ElementMixin
147
- * @mixes SlotMixin
148
186
  * @mixes ThemableMixin
149
187
  */
150
- class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerElement)))) {
188
+ class Crud extends ControllerMixin(ElementMixin(ThemableMixin(PolymerElement))) {
151
189
  static get template() {
152
190
  return html`
153
191
  <style>
@@ -233,23 +271,11 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
233
271
 
234
272
  <div id="container">
235
273
  <div id="main">
236
- <slot name="grid">
237
- <vaadin-crud-grid
238
- theme$="[[_theme]]"
239
- id="grid"
240
- include="[[include]]"
241
- exclude="[[exclude]]"
242
- no-sort="[[noSort]]"
243
- no-filter="[[noFilter]]"
244
- no-head="[[noHead]]"
245
- hide-edit-column="[[editOnClick]]"
246
- ></vaadin-crud-grid>
247
- </slot>
248
-
249
- <div id="toolbar" part="toolbar" on-click="__new">
250
- <slot name="toolbar">
251
- <vaadin-button new-button="" id="new" theme="primary">[[i18n.newItem]]</vaadin-button>
252
- </slot>
274
+ <slot name="grid"></slot>
275
+
276
+ <div id="toolbar" part="toolbar">
277
+ <slot name="toolbar"></slot>
278
+ <slot name="new-button"></slot>
253
279
  </div>
254
280
  </div>
255
281
 
@@ -283,7 +309,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
283
309
  theme$="[[_theme]]"
284
310
  id="confirmCancel"
285
311
  on-confirm="__confirmCancel"
286
- cancel
312
+ cancel-button-visible
287
313
  confirm-text="[[i18n.confirm.cancel.button.confirm]]"
288
314
  cancel-text="[[i18n.confirm.cancel.button.dismiss]]"
289
315
  header="[[i18n.confirm.cancel.title]]"
@@ -295,7 +321,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
295
321
  theme$="[[_theme]]"
296
322
  id="confirmDelete"
297
323
  on-confirm="__confirmDelete"
298
- cancel
324
+ cancel-button-visible
299
325
  confirm-text="[[i18n.confirm.delete.button.confirm]]"
300
326
  cancel-text="[[i18n.confirm.delete.button.dismiss]]"
301
327
  header="[[i18n.confirm.delete.title]]"
@@ -320,7 +346,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
320
346
  * @private
321
347
  */
322
348
  _grid: {
323
- type: HTMLElement,
349
+ type: Object,
324
350
  observer: '__gridChanged',
325
351
  },
326
352
 
@@ -329,7 +355,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
329
355
  * @private
330
356
  */
331
357
  _form: {
332
- type: HTMLElement,
358
+ type: Object,
333
359
  observer: '__formChanged',
334
360
  },
335
361
 
@@ -338,34 +364,39 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
338
364
  * @private
339
365
  */
340
366
  _saveButton: {
341
- type: HTMLElement,
342
- observer: '__saveButtonChanged',
367
+ type: Object,
343
368
  },
344
369
 
345
370
  /**
346
- * A reference to the save button which will be teleported to the dialog
371
+ * A reference to the delete button which will be teleported to the dialog
347
372
  * @private
348
373
  */
349
374
  _deleteButton: {
350
- type: HTMLElement,
351
- observer: '__deleteButtonChanged',
375
+ type: Object,
352
376
  },
353
377
 
354
378
  /**
355
- * A reference to the save button which will be teleported to the dialog
379
+ * A reference to the cancel button which will be teleported to the dialog
356
380
  * @private
357
381
  */
358
382
  _cancelButton: {
359
- type: HTMLElement,
360
- observer: '__cancelButtonChanged',
383
+ type: Object,
361
384
  },
362
385
 
363
386
  /**
364
- * A reference to the editor header element will be teleported to the dialog.
387
+ * A reference to the default editor header element created by the CRUD
365
388
  * @private
366
389
  */
367
- _headerNode: {
368
- type: HTMLElement,
390
+ _defaultHeader: {
391
+ type: Object,
392
+ },
393
+
394
+ /**
395
+ * A reference to the "New item" button
396
+ * @private
397
+ */
398
+ _newButton: {
399
+ type: Object,
369
400
  },
370
401
 
371
402
  /**
@@ -604,13 +635,15 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
604
635
 
605
636
  static get observers() {
606
637
  return [
607
- '__headerPropsChanged(_headerNode, __isNew, i18n.newItem, i18n.editItem)',
638
+ '__headerPropsChanged(_defaultHeader, __isNew, i18n.newItem, i18n.editItem)',
608
639
  '__formPropsChanged(_form, _theme, include, exclude)',
640
+ '__gridPropsChanged(_grid, _theme, include, exclude, noFilter, noHead, noSort)',
609
641
  '__i18nChanged(i18n, _grid)',
610
642
  '__editOnClickChanged(editOnClick, _grid)',
611
643
  '__saveButtonPropsChanged(_saveButton, i18n.saveItem, __isDirty)',
612
644
  '__cancelButtonPropsChanged(_cancelButton, i18n.cancel)',
613
645
  '__deleteButtonPropsChanged(_deleteButton, i18n.deleteItem, __isNew)',
646
+ '__newButtonPropsChanged(_newButton, i18n.newItem)',
614
647
  ];
615
648
  }
616
649
 
@@ -619,59 +652,66 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
619
652
  return ['bottom', 'aside'].includes(editorPosition);
620
653
  }
621
654
 
622
- /** @protected */
623
- get slots() {
624
- // NOTE: order in which the toolbar buttons are listed matters.
625
- return {
626
- ...super.slots,
627
- header: () => {
628
- return document.createElement('h3');
629
- },
630
- form: () => {
631
- return document.createElement('vaadin-crud-form');
632
- },
633
- 'save-button': () => {
634
- const button = document.createElement('vaadin-button');
635
- button.id = 'save';
636
- button.setAttribute('theme', 'primary');
637
- return button;
638
- },
639
- 'cancel-button': () => {
640
- const button = document.createElement('vaadin-button');
641
- button.id = 'cancel';
642
- button.setAttribute('theme', 'tertiary');
643
- return button;
644
- },
645
- 'delete-button': () => {
646
- const button = document.createElement('vaadin-button');
647
- button.id = 'delete';
648
- button.setAttribute('theme', 'tertiary error');
649
- return button;
650
- },
651
- };
652
- }
653
-
654
655
  constructor() {
655
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
+
656
667
  this._observer = new FlattenedNodesObserver(this, (info) => {
657
668
  this.__onDomChange(info.addedNodes);
658
669
  });
659
670
  }
660
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
+
661
689
  /** @protected */
662
690
  ready() {
663
691
  super.ready();
664
- this.__save = this.__save.bind(this);
665
- this.__cancel = this.__cancel.bind(this);
666
- this.__delete = this.__delete.bind(this);
667
- this.__onFormChange = this.__onFormChange.bind(this);
668
- this.__onGridEdit = this.__onGridEdit.bind(this);
669
- this.__onGridSizeChanged = this.__onGridSizeChanged.bind(this);
670
- this.__onGridActiveItemChanged = this.__onGridActiveItemChanged.bind(this);
671
- this._grid = this.$.grid;
692
+
672
693
  this.$.dialog.$.overlay.addEventListener('vaadin-overlay-outside-click', this.__cancel);
673
694
  this.$.dialog.$.overlay.addEventListener('vaadin-overlay-escape-press', this.__cancel);
674
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
+
675
715
  this.addController(
676
716
  new MediaQueryController(this._fullscreenMediaQuery, (matches) => {
677
717
  this._fullscreen = matches;
@@ -824,7 +864,8 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
824
864
  /** @private */
825
865
  __onDomChange(addedNodes) {
826
866
  // TODO: restore default button when a corresponding slotted button is removed.
827
- // Consider creating a controller to reuse custom helper logic from FieldMixin.
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).
828
869
  addedNodes
829
870
  .filter((node) => node.nodeType === Node.ELEMENT_NODE)
830
871
  .forEach((node) => {
@@ -842,9 +883,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
842
883
  this._form = node;
843
884
  } else if (slotAttributeValue.indexOf('button') >= 0) {
844
885
  const [button] = slotAttributeValue.split('-');
845
- this[`_${button}Button`] = node;
846
- } else if (slotAttributeValue === 'header') {
847
- this._headerNode = node;
886
+ this.__setupSlottedButton(button, node);
848
887
  }
849
888
  });
850
889
 
@@ -928,17 +967,37 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
928
967
  if (form) {
929
968
  form.include = include;
930
969
  form.exclude = exclude;
931
- form.setAttribute('theme', theme);
970
+
971
+ if (theme) {
972
+ form.setAttribute('theme', theme);
973
+ } else {
974
+ form.removeAttribute('theme');
975
+ }
932
976
  }
933
977
  }
934
978
 
935
979
  /**
936
- * @param {HTMLElement} saveButton
937
- * @param {HTMLElement | undefined} oldSaveButton
980
+ * @param {HTMLElement | undefined} form
981
+ * @param {string} theme
982
+ * @param {string | string[] | undefined} include
983
+ * @param {string | RegExp} exclude
938
984
  * @private
939
985
  */
940
- __saveButtonChanged(saveButton, oldSaveButton) {
941
- this.__setupSlottedButton(saveButton, oldSaveButton, this.__save);
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
+ }
942
1001
  }
943
1002
 
944
1003
  /**
@@ -954,15 +1013,6 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
954
1013
  }
955
1014
  }
956
1015
 
957
- /**
958
- * @param {HTMLElement} deleteButton
959
- * @param {HTMLElement | undefined} oldDeleteButton
960
- * @private
961
- */
962
- __deleteButtonChanged(deleteButton, oldDeleteButton) {
963
- this.__setupSlottedButton(deleteButton, oldDeleteButton, this.__delete);
964
- }
965
-
966
1016
  /**
967
1017
  * @param {HTMLElement | undefined} deleteButton
968
1018
  * @param {string} i18nLabel
@@ -976,15 +1026,6 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
976
1026
  }
977
1027
  }
978
1028
 
979
- /**
980
- * @param {HTMLElement} cancelButton
981
- * @param {HTMLElement | undefined} oldCancelButton
982
- * @private
983
- */
984
- __cancelButtonChanged(cancelButton, oldCancelButton) {
985
- this.__setupSlottedButton(cancelButton, oldCancelButton, this.__cancel);
986
- }
987
-
988
1029
  /**
989
1030
  * @param {HTMLElement | undefined} saveButton
990
1031
  * @param {string} i18nLabel
@@ -997,17 +1038,31 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
997
1038
  }
998
1039
 
999
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
1000
1053
  * @param {HTMLElement} newButton
1001
- * @param {HTMLElement | undefined | null} oldButton
1002
- * @param {Function} clickListener
1003
1054
  * @private
1004
1055
  */
1005
- __setupSlottedButton(newButton, oldButton, clickListener) {
1006
- if (oldButton && oldButton.parentElement) {
1007
- oldButton.parentElement.removeChild(oldButton);
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();
1008
1062
  }
1009
1063
 
1010
- newButton.addEventListener('click', clickListener);
1064
+ button.addEventListener('click', this[listener]);
1065
+ this[property] = button;
1011
1066
  }
1012
1067
 
1013
1068
  /** @private */
@@ -1018,15 +1073,17 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
1018
1073
  }
1019
1074
 
1020
1075
  /** @private */
1021
- __editOnClickChanged(editOnClick, _grid) {
1022
- if (!_grid) {
1076
+ __editOnClickChanged(editOnClick, grid) {
1077
+ if (!grid) {
1023
1078
  return;
1024
1079
  }
1025
1080
 
1081
+ grid.hideEditColumn = editOnClick;
1082
+
1026
1083
  if (editOnClick) {
1027
- _grid.addEventListener('active-item-changed', this.__onGridActiveItemChanged);
1084
+ grid.addEventListener('active-item-changed', this.__onGridActiveItemChanged);
1028
1085
  } else {
1029
- _grid.removeEventListener('active-item-changed', this.__onGridActiveItemChanged);
1086
+ grid.removeEventListener('active-item-changed', this.__onGridActiveItemChanged);
1030
1087
  }
1031
1088
  }
1032
1089
 
@@ -1127,7 +1184,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
1127
1184
  this._fields.forEach((e) => {
1128
1185
  const path = e.path || e.getAttribute('path');
1129
1186
  if (path) {
1130
- e.value = this.get(path, item);
1187
+ e.value = getProperty(path, item);
1131
1188
  }
1132
1189
  });
1133
1190
 
@@ -1136,18 +1193,6 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
1136
1193
  }
1137
1194
  }
1138
1195
 
1139
- /**
1140
- * A reference to all fields inside the [`_form`](#/elements/vaadin-crud#property-_form) element
1141
- * @return {!Array<!HTMLElement>}
1142
- * @protected
1143
- */
1144
- get _fields() {
1145
- if (!this.__fields || !this.__fields.length) {
1146
- this.__fields = Array.from(this._form.querySelectorAll('*')).filter((e) => e.validate || e.checkValidity);
1147
- }
1148
- return this.__fields;
1149
- }
1150
-
1151
1196
  /** @private */
1152
1197
  __validate() {
1153
1198
  return this._fields.every((e) => (e.validate || e.checkValidity).call(e));
@@ -1155,7 +1200,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
1155
1200
 
1156
1201
  /** @private */
1157
1202
  __setHighlightedItem(item) {
1158
- if (this._grid === this.$.grid) {
1203
+ if (this._grid === this._gridController.defaultNode) {
1159
1204
  this._grid.selectedItems = item ? [item] : [];
1160
1205
  }
1161
1206
  }
@@ -1171,11 +1216,8 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
1171
1216
  }
1172
1217
 
1173
1218
  /** @private */
1174
- __new(event) {
1175
- // This allows listening to parent element and fire only when clicking on default or custom new-button.
1176
- if (event.composedPath().some((e) => e.nodeType === 1 && e.hasAttribute('new-button'))) {
1177
- this.__confirmBeforeChangingEditedItem(null, true);
1178
- }
1219
+ __new() {
1220
+ this.__confirmBeforeChangingEditedItem(null, true);
1179
1221
  }
1180
1222
 
1181
1223
  /** @private */
@@ -1211,7 +1253,7 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
1211
1253
  this._fields.forEach((e) => {
1212
1254
  const path = e.path || e.getAttribute('path');
1213
1255
  if (path) {
1214
- this.__set(path, e.value, item);
1256
+ setProperty(path, e.value, item);
1215
1257
  }
1216
1258
  });
1217
1259
  const evt = this.dispatchEvent(new CustomEvent('save', { detail: { item }, cancelable: true }));
@@ -1223,7 +1265,9 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
1223
1265
  this.items.push(item);
1224
1266
  }
1225
1267
  } else {
1226
- this.editedItem = this.editedItem || {};
1268
+ if (!this.editedItem) {
1269
+ this.editedItem = {};
1270
+ }
1227
1271
  Object.assign(this.editedItem, item);
1228
1272
  }
1229
1273
  this._grid.clearCache();
@@ -1265,23 +1309,6 @@ class Crud extends SlotMixin(ControllerMixin(ElementMixin(ThemableMixin(PolymerE
1265
1309
  }
1266
1310
  }
1267
1311
 
1268
- /**
1269
- * Utility method for setting nested values in JSON objects but initializing empty keys unless `Polymer.Base.set`
1270
- * @private
1271
- */
1272
- __set(path, val, obj) {
1273
- if (obj && path) {
1274
- path
1275
- .split('.')
1276
- .slice(0, -1)
1277
- .reduce((o, p) => {
1278
- o[p] = o[p] || {};
1279
- return o[p];
1280
- }, obj);
1281
- this.set(path, val, obj);
1282
- }
1283
- }
1284
-
1285
1312
  /**
1286
1313
  * Fired when user wants to edit an existing item. If the default is prevented, then
1287
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' },
@@ -0,0 +1 @@
1
+ export * from './src/vaadin-crud-edit-column.js';
@@ -0,0 +1 @@
1
+ export * from './src/vaadin-crud-edit-column.js';
@@ -0,0 +1 @@
1
+ export * from './src/vaadin-crud-edit.js';
@@ -0,0 +1 @@
1
+ export * from './src/vaadin-crud-edit.js';