lightning-base-components 1.13.10-alpha → 1.14.4-alpha

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.
Files changed (69) hide show
  1. package/metadata/raptor.json +24 -0
  2. package/package.json +20 -4
  3. package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
  4. package/scopedImports/@salesforce-label-LightningDualListbox.movedOptionsPlural.js +1 -0
  5. package/scopedImports/@salesforce-label-LightningDualListbox.movedOptionsSingular.js +1 -0
  6. package/scopedImports/@salesforce-label-LightningErrorMessage.validitySelectAtleastOne.js +1 -0
  7. package/scopedImports/@salesforce-label-LightningMap.titleWithAddress.js +1 -0
  8. package/scopedImports/@salesforce-label-LightningModalBase.cancelandclose.js +1 -0
  9. package/src/lightning/ariaObserver/__component__/ariaObserver.spec.js +112 -0
  10. package/src/lightning/ariaObserver/__docs__/ariaObserver.md +142 -0
  11. package/src/lightning/{utilsPrivate/contentMutation.js → ariaObserver/ariaObserver.js} +60 -98
  12. package/src/lightning/buttonMenu/keyboard.js +0 -10
  13. package/src/lightning/card/card.html +6 -0
  14. package/src/lightning/checkboxGroup/checkboxGroup.html +2 -2
  15. package/src/lightning/checkboxGroup/checkboxGroup.js +6 -1
  16. package/src/lightning/colorPickerCustom/colorPickerCustom.js +20 -1
  17. package/src/lightning/datatable/__docs__/datatable.md +55 -0
  18. package/src/lightning/datatable/__examples__/basic/basic.html +1 -1
  19. package/src/lightning/datatable/columns-shared.js +1 -1
  20. package/src/lightning/datatable/datatable.js +98 -30
  21. package/src/lightning/datatable/errors.js +20 -9
  22. package/src/lightning/datatable/headerActions.js +77 -49
  23. package/src/lightning/datatable/infiniteLoading.js +100 -28
  24. package/src/lightning/datatable/inlineEdit.js +505 -379
  25. package/src/lightning/datatable/inlineEditShared.js +24 -0
  26. package/src/lightning/datatable/keyboard.js +162 -127
  27. package/src/lightning/datatable/renderManager.js +201 -133
  28. package/src/lightning/datatable/rowLevelActions.js +17 -13
  29. package/src/lightning/datatable/rowNumber.js +54 -20
  30. package/src/lightning/datatable/rowSelection.js +760 -0
  31. package/src/lightning/datatable/rowSelectionShared.js +79 -0
  32. package/src/lightning/datatable/rows.js +17 -6
  33. package/src/lightning/datatable/state.js +16 -2
  34. package/src/lightning/datatable/templates/div/div.css +4 -0
  35. package/src/lightning/datatable/templates/div/div.html +6 -0
  36. package/src/lightning/datatable/templates/table/table.html +5 -0
  37. package/src/lightning/datatable/utils.js +14 -0
  38. package/src/lightning/datatable/wrapText.js +77 -47
  39. package/src/lightning/dualListbox/dualListbox.html +1 -1
  40. package/src/lightning/dualListbox/dualListbox.js +42 -0
  41. package/src/lightning/formattedDateTime/__docs__/formattedDateTime.md +36 -3
  42. package/src/lightning/formattedDateTime/__examples__/datetime/datetime.html +2 -2
  43. package/src/lightning/formattedDateTime/__examples__/datetime/datetime.js +3 -1
  44. package/src/lightning/formattedDateTime/__examples__/time/time.html +1 -1
  45. package/src/lightning/formattedDateTime/__examples__/time/time.js +3 -1
  46. package/src/lightning/formattedDateTime/formattedDateTime.js +1 -0
  47. package/src/lightning/input/input.html +1 -5
  48. package/src/lightning/input/input.js +69 -48
  49. package/src/lightning/inputUtils/validity.js +12 -1
  50. package/src/lightning/pillContainer/__docs__/pillContainer.md +45 -1
  51. package/src/lightning/primitiveCellActions/primitiveCellActions.js +69 -12
  52. package/src/lightning/primitiveCellFactory/cellWithStandardLayout.html +13 -11
  53. package/src/lightning/primitiveCellFactory/primitiveCellFactory.js +13 -8
  54. package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.html +17 -14
  55. package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.js +167 -98
  56. package/src/lightning/primitiveDatatableIeditTypeFactory/primitiveDatatableIeditTypeFactory.js +94 -69
  57. package/src/lightning/primitiveDatatableStatusBar/primitiveDatatableStatusBar.html +4 -4
  58. package/src/lightning/primitiveDatatableStatusBar/primitiveDatatableStatusBar.js +4 -4
  59. package/src/lightning/primitiveHeaderActions/primitiveHeaderActions.js +99 -37
  60. package/src/lightning/progressIndicator/progressIndicator.js +1 -1
  61. package/src/lightning/progressStep/progressStep.js +30 -22
  62. package/src/lightning/staticMap/staticMap.html +1 -0
  63. package/src/lightning/staticMap/staticMap.js +39 -2
  64. package/src/lightning/utils/classSet.js +4 -1
  65. package/src/lightning/utilsPrivate/utilsPrivate.js +12 -1
  66. package/scopedImports/@salesforce-label-LightningModalBase.close.js +0 -1
  67. package/src/lightning/datatable/inlineEdit-shared.js +0 -14
  68. package/src/lightning/datatable/selector-shared.js +0 -38
  69. package/src/lightning/datatable/selector.js +0 -527
@@ -3,19 +3,21 @@
3
3
  if:true={visible}
4
4
  class="slds-popover slds-popover_edit"
5
5
  role="dialog"
6
+ aria-label={dialogAriaLabel}
6
7
  tabindex="-1"
7
8
  onblur={handleTypeElemBlur}
8
9
  onfocus={handleTypeElemFocus}
9
10
  onkeydown={handleCellKeydown}
10
- style={computedStyle}
11
- >
11
+ style={computedStyle}>
12
+
12
13
  <span class="inline-edit-form-start" tabindex="0" onfocus={handleFormStartFocus}></span>
13
14
  <div class="slds-popover__body">
14
15
  <form onsubmit={handleEditFormSubmit} novalidate>
16
+ <!-- Renders the required indicator -->
15
17
  <lightning-primitive-datatable-iedit-input-wrapper
16
18
  required={required}
17
- class="slds-grid slds-p-left_xx-small"
18
- >
19
+ class="slds-grid slds-p-left_xx-small">
20
+ <!-- Renders the appropriate input type in the inline edit panel -->
19
21
  <lightning-primitive-datatable-iedit-type-factory
20
22
  required={required}
21
23
  class="dt-type-edit-factory slds-col"
@@ -24,10 +26,11 @@
24
26
  edited-value={editedValue}
25
27
  onblur={handleTypeElemBlur}
26
28
  onfocus={handleTypeElemFocus}
27
- key={inputKey}
28
- ></lightning-primitive-datatable-iedit-type-factory>
29
+ key={inputKey}>
30
+ </lightning-primitive-datatable-iedit-type-factory>
29
31
  </lightning-primitive-datatable-iedit-input-wrapper>
30
32
  <template if:true={isMassEditEnabled}>
33
+ <!-- Checkbox to select in order to mass edit multiple rows -->
31
34
  <lightning-input
32
35
  data-mass-selection="true"
33
36
  type="checkbox"
@@ -35,32 +38,32 @@
35
38
  label={massEditCheckboxLabel}
36
39
  onchange={handleMassCheckboxChange}
37
40
  onblur={handleTypeElemBlur}
38
- onfocus={handleTypeElemFocus}
39
- ></lightning-input>
41
+ onfocus={handleTypeElemFocus}>
42
+ </lightning-input>
40
43
  </template>
41
44
  <template if:false={isMassEditEnabled}>
42
45
  <button type="submit" aria-hidden="true" tabindex="-1" class="slds-hide" value="save"></button>
43
46
  </template>
44
47
  </form>
45
48
  </div>
49
+ <!-- If in mass edit mode, render 'Cancel' and 'Apply' buttons -->
46
50
  <template if:true={isMassEditEnabled}>
47
51
  <div class="slds-popover__footer">
48
52
  <div class="slds-grid slds-grid_align-end">
49
53
  <lightning-button
50
- label={cancelLabel}
54
+ label={i18n.cancel}
51
55
  onblur={handleTypeElemBlur}
52
56
  onfocus={handleTypeElemFocus}
53
- onclick={cancelEdition}
54
- ></lightning-button>
57
+ onclick={cancelEditing}>
58
+ </lightning-button>
55
59
  <lightning-button
56
- label={applyLabel}
60
+ label={i18n.apply}
57
61
  style="margin-left: .25rem"
58
62
  variant="brand"
59
63
  onblur={handleTypeElemBlur}
60
64
  onfocus={handleTypeElemFocus}
61
65
  data-form-last-element="true"
62
- onclick={processSubmission}
63
- >
66
+ onclick={processSubmission}>
64
67
  </lightning-button>
65
68
  </div>
66
69
  </div>
@@ -1,4 +1,5 @@
1
1
  import { LightningElement, api } from 'lwc';
2
+ import labelEdit from '@salesforce/label/LightningDatatable.edit';
2
3
  import labelUpdateSelectedItems from '@salesforce/label/LightningDatatable.updateSelectedItems';
3
4
  import labelCancel from '@salesforce/label/LightningDatatable.cancel';
4
5
  import labelApply from '@salesforce/label/LightningDatatable.apply';
@@ -6,12 +7,15 @@ import { InteractingState } from 'lightning/inputUtils';
6
7
  import { formatLabel } from 'lightning/utils';
7
8
 
8
9
  const i18n = {
10
+ edit: labelEdit,
9
11
  updateSelectedItems: labelUpdateSelectedItems,
10
12
  cancel: labelCancel,
11
13
  apply: labelApply,
12
14
  };
13
15
 
14
16
  export default class PrimitiveDatatableIeditPanel extends LightningElement {
17
+ /************************* PUBLIC PROPERTIES *************************/
18
+
15
19
  @api visible;
16
20
  @api rowKeyValue;
17
21
  @api colKeyValue;
@@ -21,14 +25,80 @@ export default class PrimitiveDatatableIeditPanel extends LightningElement {
21
25
  @api numberOfSelectedRows;
22
26
  @api resolvedTypeAttributes;
23
27
 
24
- connectedCallback() {
25
- this.interactingState = new InteractingState({
26
- duration: 10,
27
- debounceInteraction: true,
28
- });
29
- this.interactingState.onleave(() => this.handlePanelLoosedFocus());
28
+ /**
29
+ * Checked when opening an edit panel to see if it's valid
30
+ * Logs an error if type is custom but does not have the
31
+ * required editTemplate with [data-inputable="true"] element
32
+ */
33
+ @api
34
+ get isEditableValid() {
35
+ if (
36
+ !this.columnDef.editableCustomType ||
37
+ this.inputableElement.isEditableCustomValid
38
+ ) {
39
+ return true;
40
+ } else if (this.columnDef.editableCustomType) {
41
+ console.error(
42
+ 'Editable custom types must define an editTemplate that includes an element with attribute data-inputable set to "true"'
43
+ );
44
+ }
45
+ return false;
46
+ }
47
+
48
+ /**
49
+ * Returns whether or not the mass edit update checkbox is selected
50
+ */
51
+ @api
52
+ get isMassEditChecked() {
53
+ return (
54
+ this.isMassEditEnabled &&
55
+ this.template.querySelector('[data-mass-selection="true"]').checked
56
+ );
57
+ }
58
+
59
+ /**
60
+ * Returns the value of the input in the inline edit panel
61
+ * This is retrieved typically when processing inline edit completion
62
+ */
63
+ @api
64
+ get value() {
65
+ return this.inputableElement ? this.inputableElement.value : null;
66
+ }
67
+
68
+ /**
69
+ * Returns the validity state object of the input in the inline edit panel
70
+ */
71
+ @api
72
+ get validity() {
73
+ return this.inputableElement.validity;
74
+ }
75
+
76
+ /************************* PUBLIC METHODS *************************/
77
+
78
+ /**
79
+ * Focuses on the input element in the inline edit panel
80
+ */
81
+ @api
82
+ focus() {
83
+ const elem = this.inputableElement;
84
+ this.interactingState.enter();
85
+
86
+ if (elem) {
87
+ elem.focus();
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Returns the <section> element which is the container of the
93
+ * positioned inline edit panel
94
+ */
95
+ @api
96
+ getPositionedElement() {
97
+ return this.template.querySelector('section');
30
98
  }
31
99
 
100
+ /************************* PRIVATE GETTERS *************************/
101
+
32
102
  get computedStyle() {
33
103
  const styleHash = {
34
104
  'z-index': 1000,
@@ -43,29 +113,41 @@ export default class PrimitiveDatatableIeditPanel extends LightningElement {
43
113
  .join(';');
44
114
  }
45
115
 
116
+ get inputableElement() {
117
+ return this.template.querySelector('.dt-type-edit-factory');
118
+ }
119
+
46
120
  get inputKey() {
47
121
  return this.rowKeyValue + this.colKeyValue;
48
122
  }
49
123
 
124
+ get required() {
125
+ return (
126
+ this.columnDef.typeAttributes &&
127
+ this.columnDef.typeAttributes.required
128
+ );
129
+ }
130
+
50
131
  get massEditCheckboxLabel() {
51
132
  return formatLabel(i18n.updateSelectedItems, this.numberOfSelectedRows);
52
133
  }
53
134
 
54
- get applyLabel() {
55
- return i18n.apply;
135
+ get dialogAriaLabel() {
136
+ const columnName = this.columnDef.label;
137
+ return `${i18n.edit} ${columnName}`;
56
138
  }
57
139
 
58
- get cancelLabel() {
59
- return i18n.cancel;
140
+ get i18n() {
141
+ return i18n;
60
142
  }
61
143
 
62
- get required() {
63
- return (
64
- this.columnDef.typeAttributes &&
65
- this.columnDef.typeAttributes.required
66
- );
67
- }
144
+ /************************* EVENT HANDLERS *************************/
68
145
 
146
+ /**
147
+ * Handles tabbing backwards out of the inline edit panel from the first form element.
148
+ * If mass edit is enabled, this will set the focus on the last element in the panel - traps focus.
149
+ * If mass edit is not enabled, it will process completion of inline edit
150
+ */
69
151
  handleFormStartFocus() {
70
152
  this.interactingState.enter();
71
153
 
@@ -79,6 +161,11 @@ export default class PrimitiveDatatableIeditPanel extends LightningElement {
79
161
  }
80
162
  }
81
163
 
164
+ /**
165
+ * Handles tabbing forwards out of the inline edit panel from the last form element.
166
+ * If mass edit is enabled, this will set focus on the first element in the panel - traps focus.
167
+ * If mass edit is not enabled, it will process the completion of inline edit
168
+ */
82
169
  handleFormEndsFocus() {
83
170
  this.interactingState.enter();
84
171
 
@@ -92,71 +179,20 @@ export default class PrimitiveDatatableIeditPanel extends LightningElement {
92
179
  }
93
180
  }
94
181
 
95
- triggerEditFinished(detail) {
96
- detail.rowKeyValue = detail.rowKeyValue || this.rowKeyValue;
97
- detail.colKeyValue = detail.colKeyValue || this.colKeyValue;
98
-
99
- const event = new CustomEvent('ieditfinished', {
100
- detail,
101
- });
102
- this.dispatchEvent(event);
103
- }
104
-
105
- @api
106
- focus() {
107
- const elem = this.inputableElement;
108
- this.interactingState.enter();
109
-
110
- if (elem) {
111
- elem.focus();
112
- }
113
- }
114
-
115
- get inputableElement() {
116
- return this.template.querySelector('.dt-type-edit-factory');
117
- }
118
-
119
182
  /**
120
- * Checked when opening an edit panel to see if it's valid
121
- * Logs an error if type is custom but does not have the
122
- * required editTemplate with [data-inputable="true"] element
183
+ * This is executed when interactingState.leave is triggered
184
+ * which happens when the inline edit panel loses focus
123
185
  */
124
- @api
125
- get isEditableValid() {
126
- if (
127
- !this.columnDef.editableCustomType ||
128
- this.inputableElement.isEditableCustomValid
129
- ) {
130
- return true;
131
- } else if (this.columnDef.editableCustomType) {
132
- console.error(
133
- 'Editable custom types must define an editTemplate that includes an element with attribute data-inputable set to "true"'
134
- );
186
+ handlePanelLostFocus() {
187
+ if (this.visible) {
188
+ this.triggerEditFinished({
189
+ reason: 'lost-focus',
190
+ });
135
191
  }
136
- return false;
137
- }
138
-
139
- @api
140
- get value() {
141
- return this.inputableElement ? this.inputableElement.value : null;
142
- }
143
-
144
- @api
145
- get validity() {
146
- return this.inputableElement.validity;
147
- }
148
-
149
- @api
150
- get isMassEditChecked() {
151
- return (
152
- this.isMassEditEnabled &&
153
- this.template.querySelector('[data-mass-selection="true"]').checked
154
- );
155
192
  }
156
193
 
157
- @api
158
- getPositionedElement() {
159
- return this.template.querySelector('section');
194
+ handleTypeElemFocus() {
195
+ this.interactingState.enter();
160
196
  }
161
197
 
162
198
  handleTypeElemBlur() {
@@ -165,10 +201,6 @@ export default class PrimitiveDatatableIeditPanel extends LightningElement {
165
201
  }
166
202
  }
167
203
 
168
- handleTypeElemFocus() {
169
- this.interactingState.enter();
170
- }
171
-
172
204
  handleEditFormSubmit(event) {
173
205
  event.preventDefault();
174
206
  event.stopPropagation();
@@ -180,24 +212,71 @@ export default class PrimitiveDatatableIeditPanel extends LightningElement {
180
212
  return false;
181
213
  }
182
214
 
215
+ /**
216
+ * If the Escape key is pressed on the inline edit panel,
217
+ * we prevent default action, stop propagation of the event
218
+ * and close the inline edit panel
219
+ *
220
+ * @param {KeyboardEvent} event - keydown
221
+ */
183
222
  handleCellKeydown(event) {
184
223
  const { keyCode } = event;
185
224
 
186
225
  if (keyCode === 27) {
187
226
  // Esc key
227
+ event.preventDefault();
188
228
  event.stopPropagation();
189
- this.cancelEdition();
229
+ this.cancelEditing();
190
230
  }
191
231
  }
192
232
 
193
- handlePanelLoosedFocus() {
194
- if (this.visible) {
195
- this.triggerEditFinished({
196
- reason: 'loosed-focus',
197
- });
198
- }
233
+ /************************* EVENT DISPATCHERS *************************/
234
+
235
+ /**
236
+ * Change handler for the mass edit checkbox.
237
+ * Dispatches the `masscheckboxchange` event along with the new checked value
238
+ *
239
+ * @param {CustomEvent} event - `change` event from lightning-input
240
+ */
241
+ handleMassCheckboxChange(event) {
242
+ const customEvent = new CustomEvent('masscheckboxchange', {
243
+ detail: {
244
+ checked: event.detail.checked,
245
+ },
246
+ });
247
+
248
+ this.dispatchEvent(customEvent);
199
249
  }
200
250
 
251
+ /**
252
+ * Dispatches the `ieditfinished` event with the detail object containing
253
+ * the reason for inline edit finishing and the rowKeyValue and colKeyValue
254
+ * with which the particular cell which was edited can be identified.
255
+ *
256
+ * @param {Object} detail - typically contains the reason for inline edit finishing
257
+ */
258
+ triggerEditFinished(detail) {
259
+ detail.rowKeyValue = detail.rowKeyValue || this.rowKeyValue;
260
+ detail.colKeyValue = detail.colKeyValue || this.colKeyValue;
261
+
262
+ const event = new CustomEvent('ieditfinished', {
263
+ detail,
264
+ });
265
+ this.dispatchEvent(event);
266
+ }
267
+
268
+ /************************* LIFECYCLE HOOKS *************************/
269
+
270
+ connectedCallback() {
271
+ this.interactingState = new InteractingState({
272
+ duration: 10,
273
+ debounceInteraction: true,
274
+ });
275
+ this.interactingState.onleave(() => this.handlePanelLostFocus());
276
+ }
277
+
278
+ /************************* HELPER FUNCTIONS *************************/
279
+
201
280
  focusLastElement() {
202
281
  this.template.querySelector('[data-form-last-element="true"]').focus();
203
282
  }
@@ -210,19 +289,9 @@ export default class PrimitiveDatatableIeditPanel extends LightningElement {
210
289
  }
211
290
  }
212
291
 
213
- cancelEdition() {
292
+ cancelEditing() {
214
293
  this.triggerEditFinished({
215
294
  reason: 'edit-canceled',
216
295
  });
217
296
  }
218
-
219
- handleMassCheckboxChange(event) {
220
- const customEvent = new CustomEvent('masscheckboxchange', {
221
- detail: {
222
- checked: event.detail.checked,
223
- },
224
- });
225
-
226
- this.dispatchEvent(customEvent);
227
- }
228
297
  }
@@ -13,7 +13,7 @@ import DateLocalTpl from './dateLocal.html';
13
13
  import DateTpl from './date.html';
14
14
  import DefaultTpl from './default.html';
15
15
 
16
- const TYPE_TPL_MAPPINGS = {
16
+ const TYPE_TEMPLATE_MAPPINGS = {
17
17
  text: TextTpl,
18
18
  phone: PhoneTpl,
19
19
  email: EmailTpl,
@@ -25,10 +25,14 @@ const TYPE_TPL_MAPPINGS = {
25
25
  'date-local': DateLocalTpl,
26
26
  date: DateTpl,
27
27
  };
28
- const INVALID_TYPE_FOR_EDIT = 'column type not supported for inline edit';
28
+ const INVALID_TYPE_MESSAGE = 'column type not supported for inline edit';
29
29
 
30
30
  export default class LightningPrimitiveDatatableIeditTypeFactory extends LightningElement {
31
+ // Private Variables
31
32
  columnLabel;
33
+
34
+ /***************************** PUBLIC PROPERTIES *****************************/
35
+
32
36
  @api editedValue;
33
37
  @api required;
34
38
  @api typeAttributes;
@@ -41,54 +45,23 @@ export default class LightningPrimitiveDatatableIeditTypeFactory extends Lightni
41
45
  set columnDef(value) {
42
46
  assert(
43
47
  // eslint-disable-next-line no-prototype-builtins
44
- TYPE_TPL_MAPPINGS.hasOwnProperty(value.type) ||
48
+ TYPE_TEMPLATE_MAPPINGS.hasOwnProperty(value.type) ||
45
49
  value.editableCustomType,
46
- INVALID_TYPE_FOR_EDIT
50
+ INVALID_TYPE_MESSAGE
47
51
  );
48
52
 
49
53
  this._columnDef = value;
50
54
  this.columnLabel = value.label;
51
55
  }
52
56
 
53
- get columnType() {
54
- return this._columnDef.type;
55
- }
56
-
57
- render() {
58
- return this.isValidCustomType
59
- ? this.customEditTemplate
60
- : TYPE_TPL_MAPPINGS[this.columnType] || DefaultTpl;
61
- }
62
-
63
- connectedCallback() {
64
- this._blurHandler = this.handleComponentBlur.bind(this);
65
- this._focusHandler = this.handleComponentFocus.bind(this);
66
- this._changeHandler = this.handleComponentChange.bind(this);
67
- }
68
-
69
- renderedCallback() {
70
- if (this.concreteComponent) {
71
- this.concreteComponent.addEventListener('blur', this._blurHandler);
72
- this.concreteComponent.addEventListener(
73
- 'focus',
74
- this._focusHandler
75
- );
76
- this.concreteComponent.addEventListener(
77
- 'change',
78
- this._changeHandler
79
- );
80
- }
81
- }
82
-
83
- get concreteComponent() {
84
- return this.template.querySelector('[data-inputable="true"]');
85
- }
86
-
57
+ /**
58
+ * Checks if type is an custom type that is editable and
59
+ * has an editTemplate that contains [data-inputable="true"]
60
+ * Used when checking if cell can actually be edited
61
+ */
87
62
  @api
88
- focus() {
89
- if (this.concreteComponent) {
90
- this.concreteComponent.focus();
91
- }
63
+ get isEditableCustomValid() {
64
+ return this.isValidCustomType && this.concreteComponent;
92
65
  }
93
66
 
94
67
  @api
@@ -104,11 +77,47 @@ export default class LightningPrimitiveDatatableIeditTypeFactory extends Lightni
104
77
  return this.concreteComponent.validity;
105
78
  }
106
79
 
80
+ /***************************** PUBLIC METHODS *****************************/
81
+
82
+ /**
83
+ * Focuses on the input component that is rendered by the type factory
84
+ */
85
+ @api
86
+ focus() {
87
+ if (this.concreteComponent) {
88
+ this.concreteComponent.focus();
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Displays error message if the input is invalid
94
+ */
107
95
  @api
108
96
  showHelpMessageIfInvalid() {
109
97
  this.concreteComponent.showHelpMessageIfInvalid();
110
98
  }
111
99
 
100
+ /***************************** PRIVATE GETTERS *****************************/
101
+
102
+ get columnType() {
103
+ return this._columnDef.type;
104
+ }
105
+
106
+ get concreteComponent() {
107
+ return this.template.querySelector('[data-inputable="true"]');
108
+ }
109
+
110
+ /**
111
+ * Returns editTemplate defined for custom type template
112
+ */
113
+ get customEditTemplate() {
114
+ return this._columnDef.editTemplate;
115
+ }
116
+
117
+ /**
118
+ * Retrieves the date set in the column and converts it to a value
119
+ * that can be passed into lightning-input type="datetime"
120
+ */
112
121
  get editedDateValue() {
113
122
  const dateValue = new Date(this.editedValue);
114
123
 
@@ -119,27 +128,17 @@ export default class LightningPrimitiveDatatableIeditTypeFactory extends Lightni
119
128
  return dateValue.toISOString();
120
129
  }
121
130
 
122
- handleComponentFocus() {
123
- this.dispatchEvent(new CustomEvent('focus'));
124
- }
125
-
126
- handleComponentBlur() {
127
- this.dispatchEvent(new CustomEvent('blur'));
128
- }
129
-
130
- handleComponentChange() {
131
- this.showHelpMessageIfInvalid();
132
- }
133
-
134
131
  /**
135
- * Returns editTemplate defined for custom type template
132
+ * Checks this custom type is editable and has editTemplate defined
136
133
  */
137
- get customEditTemplate() {
138
- return this._columnDef.editTemplate;
134
+ get isValidCustomType() {
135
+ return (
136
+ this._columnDef.editableCustomType && this._columnDef.editTemplate
137
+ );
139
138
  }
140
139
 
141
140
  /**
142
- * for percent, currency types use if step passed in, if not fallback to default
141
+ * For percent, currency types use if step passed in, if not fallback to default
143
142
  * @returns {*|string}
144
143
  */
145
144
  get typeAttributeStep() {
@@ -151,22 +150,48 @@ export default class LightningPrimitiveDatatableIeditTypeFactory extends Lightni
151
150
  );
152
151
  }
153
152
 
153
+ /***************************** EVENT HANDLERS *****************************/
154
+
155
+ handleComponentFocus() {
156
+ this.dispatchEvent(new CustomEvent('focus'));
157
+ }
158
+
159
+ handleComponentBlur() {
160
+ this.dispatchEvent(new CustomEvent('blur'));
161
+ }
162
+
163
+ handleComponentChange() {
164
+ this.showHelpMessageIfInvalid();
165
+ }
166
+
167
+ /***************************** LIFECYCLE HOOKS *****************************/
168
+
154
169
  /**
155
- * Checks this custom type is editable and has editTemplate defined
170
+ * Renders the appropriate template based on the column type
156
171
  */
157
- get isValidCustomType() {
158
- return (
159
- this._columnDef.editableCustomType && this._columnDef.editTemplate
160
- );
172
+ render() {
173
+ return this.isValidCustomType
174
+ ? this.customEditTemplate
175
+ : TYPE_TEMPLATE_MAPPINGS[this.columnType] || DefaultTpl;
161
176
  }
162
177
 
163
178
  /**
164
- * Checks if type is an custom type that is editable and
165
- * has an editTemplate that contains [data-inputable="true"]
166
- * Used when checking if cell can actually be edited
179
+ * Attaches event handlers for `focus`, `blur` and `change` events
167
180
  */
168
- @api
169
- get isEditableCustomValid() {
170
- return this.isValidCustomType && this.concreteComponent;
181
+ renderedCallback() {
182
+ if (this.concreteComponent) {
183
+ this.concreteComponent.addEventListener(
184
+ 'focus',
185
+ this.handleComponentFocus.bind(this)
186
+ );
187
+ this.concreteComponent.addEventListener(
188
+ 'blur',
189
+ this.handleComponentBlur.bind(this)
190
+ );
191
+ this.concreteComponent.addEventListener(
192
+ 'change',
193
+ this.handleComponentChange.bind(this)
194
+ );
195
+ }
171
196
  }
172
197
  }