lightning-base-components 1.13.6-alpha → 1.14.1-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.
- package/metadata/raptor.json +104 -2
- package/package.json +37 -1
- package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
- package/scopedImports/@salesforce-label-LightningAlert.defaultLabel.js +1 -0
- package/scopedImports/@salesforce-label-LightningConfirm.defaultLabel.js +1 -0
- package/scopedImports/@salesforce-label-LightningDateTimePicker.selectDateFor.js +1 -0
- package/scopedImports/@salesforce-label-LightningInteractiveDialogBase.cancel.js +1 -0
- package/scopedImports/@salesforce-label-LightningInteractiveDialogBase.ok.js +1 -0
- package/scopedImports/@salesforce-label-LightningLookup.recentItems.js +1 -0
- package/scopedImports/@salesforce-label-LightningModalBase.close.js +1 -0
- package/scopedImports/@salesforce-label-LightningModalBase.waitstate.js +1 -0
- package/scopedImports/@salesforce-label-LightningPrompt.defaultLabel.js +1 -0
- package/src/lightning/baseCombobox/baseCombobox.html +50 -24
- package/src/lightning/baseCombobox/baseCombobox.js +53 -28
- package/src/lightning/card/card.html +7 -1
- package/src/lightning/card/card.js +30 -2
- package/src/lightning/card/utils.js +14 -0
- package/src/lightning/combobox/combobox.css +12 -0
- package/src/lightning/combobox/combobox.html +1 -0
- package/src/lightning/datatable/__docs__/datatable.md +40 -13
- package/src/lightning/datatable/columnWidthManager.js +8 -4
- package/src/lightning/datatable/columns-shared.js +8 -7
- package/src/lightning/datatable/columns.js +38 -4
- package/src/lightning/datatable/datatable.js +932 -727
- package/src/lightning/datatable/datatableResizeObserver.js +1 -1
- package/src/lightning/datatable/inlineEdit.js +15 -3
- package/src/lightning/datatable/keyboard.js +1078 -935
- package/src/lightning/datatable/resizer.js +92 -109
- package/src/lightning/datatable/rows.js +245 -59
- package/src/lightning/datatable/sort.js +83 -28
- package/src/lightning/datatable/{normalizer.js → state.js} +16 -28
- package/src/lightning/datatable/templates/div/div.css +53 -0
- package/src/lightning/datatable/templates/div/div.html +272 -0
- package/src/lightning/datatable/{datatable.css → templates/table/table.css} +0 -0
- package/src/lightning/datatable/templates/table/table.html +260 -0
- package/src/lightning/datatable/widthManagerShared.js +1 -1
- package/src/lightning/datepicker/datepicker.html +3 -3
- package/src/lightning/datepicker/datepicker.js +6 -2
- package/src/lightning/datetimepicker/datetimepicker.html +3 -4
- package/src/lightning/datetimepicker/datetimepicker.js +0 -2
- package/src/lightning/formattedRichText/__docs__/formattedRichText.md +1 -0
- package/src/lightning/helptext/helptext.js +8 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/asset_audit.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/attach.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/contract_payment.html +10 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/field_sales.html +8 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/historical_adherence.html +9 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/med_rec_recommendation.html +8 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/med_rec_statement_recommendation.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/medication_dispense.html +11 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/medication_reconciliation.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/report_type.html +9 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/story.html +2 -4
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/tour.html +9 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/tour_check.html +8 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/unified_health_score.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/workforce_engagement.html +8 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/templates.js +26 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/asset_audit.html +9 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/collection_alt.html +8 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/contract_doc.html +8 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/contract_payment.html +10 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/einstein.html +2 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/entitlement.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/field_sales.html +8 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/signature.html +9 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/tour.html +9 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/tour_check.html +8 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/truck.html +10 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/workforce_engagement.html +8 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/asset_audit.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/attach.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/contract_payment.html +10 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/field_sales.html +8 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/historical_adherence.html +9 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/med_rec_recommendation.html +8 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/med_rec_statement_recommendation.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/medication_dispense.html +11 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/medication_reconciliation.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/report_type.html +9 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/story.html +2 -4
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/tour.html +9 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/tour_check.html +8 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/unified_health_score.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/workforce_engagement.html +8 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/templates.js +26 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/asset_audit.html +9 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/collection_alt.html +8 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/contract_doc.html +8 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/contract_payment.html +10 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/einstein.html +2 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/entitlement.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/field_sales.html +8 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/signature.html +9 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/tour.html +9 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/tour_check.html +8 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/truck.html +10 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/workforce_engagement.html +8 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/asset_audit.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/attach.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/contract_payment.html +10 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/field_sales.html +8 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/historical_adherence.html +9 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/med_rec_recommendation.html +8 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/med_rec_statement_recommendation.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/medication_dispense.html +11 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/medication_reconciliation.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/report_type.html +9 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/story.html +2 -4
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/tour.html +9 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/tour_check.html +8 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/unified_health_score.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/workforce_engagement.html +8 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/templates.js +15 -1
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/asset_audit.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/attach.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/contract_payment.html +10 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/field_sales.html +8 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/historical_adherence.html +9 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/med_rec_recommendation.html +8 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/med_rec_statement_recommendation.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/medication_dispense.html +11 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/medication_reconciliation.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/report_type.html +9 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/story.html +2 -4
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/tour.html +9 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/tour_check.html +8 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/unified_health_score.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/workforce_engagement.html +8 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/templates.js +15 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/templates.js +12 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/asset_audit.html +9 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/collection_alt.html +8 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/contract_doc.html +8 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/contract_payment.html +10 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/einstein.html +2 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/entitlement.html +7 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/field_sales.html +8 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/signature.html +9 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/tour.html +9 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/tour_check.html +8 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/truck.html +10 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/workforce_engagement.html +8 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/templates.js +12 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/asset_audit.html +9 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/collection_alt.html +8 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/contract_doc.html +8 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/contract_payment.html +10 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/einstein.html +2 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/entitlement.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/field_sales.html +8 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/signature.html +9 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/tour.html +9 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/tour_check.html +8 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/truck.html +10 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/workforce_engagement.html +8 -0
- package/src/lightning/input/__docs__/input.md +4 -0
- package/src/lightning/input/input.html +0 -1
- package/src/lightning/input/input.js +31 -30
- package/src/lightning/pill/link.html +1 -1
- package/src/lightning/pill/pill.js +18 -0
- package/src/lightning/pill/plainLink.html +2 -0
- package/src/lightning/pillContainer/barePillContainer.html +5 -5
- package/src/lightning/pillContainer/pillContainer.js +5 -4
- package/src/lightning/pillContainer/standardPillContainer.html +5 -5
- package/src/lightning/positionLibrary/__component__/positionLibraryBounding.spec.js +8 -6
- package/src/lightning/positionLibrary/__component__/x/bounding/bounding.html +1 -1
- package/src/lightning/positionLibrary/__component__/x/bounding/bounding.js +6 -9
- package/src/lightning/positionLibrary/direction.js +17 -5
- package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.js +20 -0
- package/src/lightning/primitiveDatatableIeditTypeFactory/primitiveDatatableIeditTypeFactory.js +10 -0
- package/src/lightning/primitiveDatatableStatusBar/primitiveDatatableStatusBar.js +17 -3
- package/src/lightning/primitiveDatatableTooltip/primitiveDatatableTooltip.js +1 -0
- package/src/lightning/primitiveHeaderFactory/nonsortableHeader.html +5 -4
- package/src/lightning/primitiveHeaderFactory/primitiveHeaderFactory.js +255 -94
- package/src/lightning/primitiveHeaderFactory/selectableHeader.html +25 -23
- package/src/lightning/primitiveHeaderFactory/sortableHeader.html +13 -9
- package/src/lightning/progressIndicator/progressIndicator.js +30 -9
- package/src/lightning/progressRing/progressRing.html +6 -0
- package/src/lightning/progressRing/progressRing.js +98 -3
- package/src/lightning/progressStep/progressStep.js +6 -3
- package/src/lightning/timepicker/timepicker.html +1 -0
- package/src/lightning/utilsPrivate/aria.js +30 -0
- package/src/lightning/utilsPrivate/utilsPrivate.js +12 -2
- package/src/lightning/datatable/datatable.html +0 -237
- package/src/lightning/datatable/keys.js +0 -32
- package/src/lightning/utilsPrivate/contentMutation.js +0 -273
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LightningElement, api, track, unwrap } from 'lwc';
|
|
2
|
-
import
|
|
2
|
+
import tableTemplate from './templates/table/table.html';
|
|
3
|
+
import divTemplate from './templates/div/div.html';
|
|
3
4
|
import { classSet } from 'lightning/utils';
|
|
4
5
|
import {
|
|
5
6
|
normalizeBoolean,
|
|
@@ -10,7 +11,8 @@ import {
|
|
|
10
11
|
} from 'lightning/utilsPrivate';
|
|
11
12
|
import { LightningDatatableResizeObserver } from './datatableResizeObserver';
|
|
12
13
|
import { ColumnWidthManager } from './columnWidthManager';
|
|
13
|
-
import {
|
|
14
|
+
import { getDefaultState } from './state';
|
|
15
|
+
import { getColumns, normalizeColumns, generateHeaderIndexes } from './columns';
|
|
14
16
|
import {
|
|
15
17
|
setData,
|
|
16
18
|
getData,
|
|
@@ -18,6 +20,8 @@ import {
|
|
|
18
20
|
setKeyField,
|
|
19
21
|
getKeyField,
|
|
20
22
|
hasValidKeyField,
|
|
23
|
+
updateCellClassForRoleBasedMode,
|
|
24
|
+
recomputeCellStyles,
|
|
21
25
|
} from './rows';
|
|
22
26
|
import {
|
|
23
27
|
isResizeColumnDisabled,
|
|
@@ -31,7 +35,7 @@ import {
|
|
|
31
35
|
getColumnsWidths,
|
|
32
36
|
resizeColumnWithDelta,
|
|
33
37
|
getCustomerColumnWidths,
|
|
34
|
-
|
|
38
|
+
getCSSWidthStyleOfTable,
|
|
35
39
|
updateColumnWidthsMetadata,
|
|
36
40
|
getResizerDefaultState,
|
|
37
41
|
} from './resizer';
|
|
@@ -52,7 +56,7 @@ import {
|
|
|
52
56
|
} from './selector';
|
|
53
57
|
import {
|
|
54
58
|
syncActiveCell,
|
|
55
|
-
|
|
59
|
+
handleKeydownOnCell,
|
|
56
60
|
updateActiveCell,
|
|
57
61
|
setBlurActiveCell,
|
|
58
62
|
setFocusActiveCell,
|
|
@@ -63,7 +67,7 @@ import {
|
|
|
63
67
|
updateTabIndexActiveRow,
|
|
64
68
|
unsetRowNavigationMode,
|
|
65
69
|
updateRowNavigationMode,
|
|
66
|
-
|
|
70
|
+
handleDatatableFocusOut,
|
|
67
71
|
handleDatatableFocusIn,
|
|
68
72
|
updateTabIndexRow,
|
|
69
73
|
getIndexesActiveCell,
|
|
@@ -73,7 +77,7 @@ import {
|
|
|
73
77
|
resetCellToFocusFromPrev,
|
|
74
78
|
datatableHasFocus,
|
|
75
79
|
setCellClickedForFocus,
|
|
76
|
-
|
|
80
|
+
handleKeydownOnTable,
|
|
77
81
|
addFocusStylesToActiveCell,
|
|
78
82
|
refocusCellElement,
|
|
79
83
|
} from './keyboard';
|
|
@@ -83,7 +87,6 @@ import {
|
|
|
83
87
|
hasRowNumberColumn,
|
|
84
88
|
setShowRowNumberColumn,
|
|
85
89
|
} from './rowNumber';
|
|
86
|
-
import { getColumns, normalizeColumns } from './columns';
|
|
87
90
|
import {
|
|
88
91
|
handleLoadMoreCheck,
|
|
89
92
|
isInfiniteLoadingEnabled,
|
|
@@ -142,8 +145,6 @@ import DatatableTypes from './types';
|
|
|
142
145
|
import labelAriaLiveNavigationMode from '@salesforce/label/LightningDatatable.ariaLiveNavigationMode';
|
|
143
146
|
import labelAriaLiveActionMode from '@salesforce/label/LightningDatatable.ariaLiveActionMode';
|
|
144
147
|
|
|
145
|
-
const typesMap = new WeakMap();
|
|
146
|
-
|
|
147
148
|
const i18n = {
|
|
148
149
|
ariaLiveNavigationMode: labelAriaLiveNavigationMode,
|
|
149
150
|
ariaLiveActionMode: labelAriaLiveActionMode,
|
|
@@ -153,53 +154,87 @@ const i18n = {
|
|
|
153
154
|
* A table that displays rows and columns of data.
|
|
154
155
|
*/
|
|
155
156
|
export default class LightningDatatable extends LightningElement {
|
|
156
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Usage of State Object vs Private Variable:
|
|
159
|
+
* This is by no means a definitive set of rules and we should add/modify these
|
|
160
|
+
* guidelines with time as we work on the datatable and find specific reasons.
|
|
161
|
+
*
|
|
162
|
+
* In general, the main reason for using the `state` object is to take advantage
|
|
163
|
+
* of LWC's reactivity. In the `state` object we store properties that are required
|
|
164
|
+
* to trigger an update/re-render of the datatable.
|
|
165
|
+
*
|
|
166
|
+
* There are no observable perf implications of using the state object vs
|
|
167
|
+
* private variables. See W-10006095 for details.
|
|
168
|
+
*
|
|
169
|
+
* Guidelines:
|
|
170
|
+
* 1. If possible, avoid adding properties to the state object if it does not
|
|
171
|
+
* trigger an update or re-render of the datatable.
|
|
172
|
+
* 2. You may look to add properties to the state object if that property is
|
|
173
|
+
* required in different areas of the datatable and/or if not adding to the
|
|
174
|
+
* state will significantly add to the complexity of the component.
|
|
175
|
+
* 3. Goal: Breakdown the 'state' object - Right now the state object contains a
|
|
176
|
+
* lot of metadata and we pass around the monolith everywhere even when most
|
|
177
|
+
* of the information is not required. If you have the opportunity, look to
|
|
178
|
+
* separate or break down the state object even if that means adding a new
|
|
179
|
+
* tracked object. This will help us logically separate various modules over
|
|
180
|
+
* time and pass around only necessary information leading to cleaner,
|
|
181
|
+
* more readable and organized code.
|
|
182
|
+
*/
|
|
183
|
+
|
|
184
|
+
// Tracked Objects
|
|
157
185
|
@track state = getDefaultState();
|
|
186
|
+
@track widthsData = getResizerDefaultState();
|
|
158
187
|
|
|
188
|
+
// Private Variables
|
|
189
|
+
_actionsMinHeightStyle = ''; // Min height required while actions menu is opened
|
|
159
190
|
_columns = [];
|
|
160
|
-
_hideCheckboxColumn = false;
|
|
161
|
-
_draftValues = [];
|
|
162
|
-
customerSelectedRows = null;
|
|
163
|
-
privateDatatableId = generateUniqueId('lgt-datatable');
|
|
164
191
|
_columnWidthsMode = 'fixed';
|
|
165
|
-
|
|
192
|
+
_customerSelectedRows = null;
|
|
193
|
+
_datatableId = generateUniqueId('lgt-datatable');
|
|
194
|
+
_draftValues = [];
|
|
195
|
+
_isResizing = false; // Whether resizing is in progress
|
|
196
|
+
_privateTypes = {};
|
|
197
|
+
_privateWidthObserver = null; // Instance of LightningDatatableResizeObserver
|
|
198
|
+
_renderMode = 'table';
|
|
166
199
|
_renderedRowCount = 0;
|
|
200
|
+
_suppressBottomBar = false;
|
|
201
|
+
|
|
202
|
+
/************************* PUBLIC PROPERTIES *************************/
|
|
167
203
|
|
|
168
204
|
/**
|
|
169
205
|
* Public property for passing `aria-label` down to the child table element.
|
|
170
206
|
*/
|
|
171
|
-
|
|
207
|
+
ariaLabel = null;
|
|
172
208
|
|
|
173
209
|
/**
|
|
174
210
|
* Public property for passing `aria-labelledby` down to the child table element.
|
|
175
211
|
*/
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
// Whether resizing is in progress
|
|
179
|
-
_isResizing = false;
|
|
180
|
-
|
|
181
|
-
constructor() {
|
|
182
|
-
super();
|
|
183
|
-
if (!typesMap.has(this.constructor)) {
|
|
184
|
-
const privateTypes = new DatatableTypes(
|
|
185
|
-
this.constructor.customTypes
|
|
186
|
-
);
|
|
187
|
-
typesMap.set(this.constructor, privateTypes);
|
|
188
|
-
}
|
|
189
|
-
this._columnWidthManager = new ColumnWidthManager(this.widthsData);
|
|
190
|
-
this.updateRowsAndCellIndexes = updateRowsAndCellIndexes.bind(this);
|
|
212
|
+
ariaLabelledBy = null;
|
|
191
213
|
|
|
192
|
-
|
|
214
|
+
/**
|
|
215
|
+
* Specifies how column widths are calculated. Set to 'fixed' for columns with equal widths.
|
|
216
|
+
* Set to 'auto' for column widths that are based on the width of the column content and the table width. The default is 'fixed'.
|
|
217
|
+
* @type {string}
|
|
218
|
+
* @default fixed
|
|
219
|
+
*/
|
|
220
|
+
@api
|
|
221
|
+
get columnWidthsMode() {
|
|
222
|
+
return this.widthsData.columnWidthsMode;
|
|
193
223
|
}
|
|
194
224
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
225
|
+
set columnWidthsMode(value) {
|
|
226
|
+
const normalizedValue = normalizeString(value, {
|
|
227
|
+
fallbackValue: 'fixed',
|
|
228
|
+
validValues: ['fixed', 'auto'],
|
|
229
|
+
});
|
|
230
|
+
this._columnWidthManager.columnWidthMode = normalizedValue;
|
|
198
231
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
232
|
+
const { state, widthsData } = this;
|
|
233
|
+
if (widthsData.columnWidthsMode !== normalizedValue) {
|
|
234
|
+
this._columnWidthManager.handleWidthModeChange(getColumns(state));
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
widthsData.columnWidthsMode = normalizedValue;
|
|
203
238
|
}
|
|
204
239
|
|
|
205
240
|
/**
|
|
@@ -213,22 +248,20 @@ export default class LightningDatatable extends LightningElement {
|
|
|
213
248
|
return this._columns;
|
|
214
249
|
}
|
|
215
250
|
|
|
251
|
+
set columns(value) {
|
|
252
|
+
this._columns = Array.isArray(value) ? value : [];
|
|
253
|
+
this.updateColumns(this._columns);
|
|
254
|
+
this._columnWidthManager.handleColumnsChange(getColumns(this.state));
|
|
255
|
+
}
|
|
256
|
+
|
|
216
257
|
/**
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
* The text in the last line is truncated and shown with an ellipsis.
|
|
220
|
-
* @type {integer}
|
|
258
|
+
* The array of data to be displayed.
|
|
259
|
+
* @type {array}
|
|
221
260
|
*/
|
|
222
261
|
@api
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
set wrapTextMaxLines(value) {
|
|
228
|
-
const { state } = this;
|
|
229
|
-
setWrapTextMaxLines(state, value);
|
|
230
|
-
this._columnWidthManager.wrapTextMaxLines = state.wrapTextMaxLines;
|
|
231
|
-
this.updateRowsAndCellIndexes(this.state);
|
|
262
|
+
// eslint-disable-next-line @lwc/lwc/valid-api
|
|
263
|
+
get data() {
|
|
264
|
+
return getData(this.state);
|
|
232
265
|
}
|
|
233
266
|
|
|
234
267
|
set data(value) {
|
|
@@ -245,52 +278,75 @@ export default class LightningDatatable extends LightningElement {
|
|
|
245
278
|
if (hasValidKeyField(this.state)) {
|
|
246
279
|
this.updateRowsState();
|
|
247
280
|
}
|
|
248
|
-
if (this.
|
|
249
|
-
this.setSelectedRows(this.
|
|
281
|
+
if (this._customerSelectedRows) {
|
|
282
|
+
this.setSelectedRows(this._customerSelectedRows);
|
|
250
283
|
}
|
|
251
284
|
}
|
|
252
285
|
|
|
253
286
|
/**
|
|
254
|
-
*
|
|
255
|
-
*
|
|
287
|
+
* Specifies the default sorting direction on an unsorted column.
|
|
288
|
+
* Valid options include 'asc' and 'desc'.
|
|
289
|
+
* The default is 'asc' for sorting in ascending order.
|
|
290
|
+
* @type {string}
|
|
291
|
+
* @default asc
|
|
256
292
|
*/
|
|
257
293
|
@api
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
return getData(this.state);
|
|
294
|
+
get defaultSortDirection() {
|
|
295
|
+
return getDefaultSortDirection(this.state);
|
|
261
296
|
}
|
|
262
297
|
|
|
263
|
-
set
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
this.updateRowsState();
|
|
298
|
+
set defaultSortDirection(value) {
|
|
299
|
+
setDefaultSortDirection(this.state, value);
|
|
300
|
+
updateSorting(this.state);
|
|
267
301
|
}
|
|
268
302
|
|
|
269
303
|
/**
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
* @type {string}
|
|
273
|
-
* @required
|
|
304
|
+
* The current values per row that are provided during inline edit.
|
|
305
|
+
* @type {object}
|
|
274
306
|
*/
|
|
275
307
|
@api
|
|
276
|
-
get
|
|
277
|
-
return
|
|
308
|
+
get draftValues() {
|
|
309
|
+
return getDirtyValues(this.state);
|
|
278
310
|
}
|
|
279
311
|
|
|
280
|
-
set
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
this._hideCheckboxColumn = normalizedValue;
|
|
312
|
+
set draftValues(value) {
|
|
313
|
+
this._draftValues = value;
|
|
314
|
+
setDirtyValues(this.state, value);
|
|
284
315
|
|
|
285
|
-
this.
|
|
286
|
-
state
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
);
|
|
316
|
+
if (hasValidKeyField(this.state)) {
|
|
317
|
+
this.updateRowsAndCellIndexes(this.state);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
290
320
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
321
|
+
/**
|
|
322
|
+
* If present, you can load a subset of data and then display more
|
|
323
|
+
* when users scroll to the end of the table.
|
|
324
|
+
* Use with the onloadmore event handler to retrieve more data.
|
|
325
|
+
* @type {boolean}
|
|
326
|
+
* @default false
|
|
327
|
+
*/
|
|
328
|
+
@api
|
|
329
|
+
get enableInfiniteLoading() {
|
|
330
|
+
return isInfiniteLoadingEnabled(this.state);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
set enableInfiniteLoading(value) {
|
|
334
|
+
setInfiniteLoading(this.state, value);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Specifies an object containing information about cell level, row level, and table level errors.
|
|
339
|
+
* When it's set, error messages are displayed on the table accordingly.
|
|
340
|
+
* @type {object}
|
|
341
|
+
*/
|
|
342
|
+
@api
|
|
343
|
+
get errors() {
|
|
344
|
+
return getErrors(this.state);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
set errors(value) {
|
|
348
|
+
setErrors(this.state, value);
|
|
349
|
+
this.updateRowsState();
|
|
294
350
|
}
|
|
295
351
|
|
|
296
352
|
/**
|
|
@@ -300,85 +356,83 @@ export default class LightningDatatable extends LightningElement {
|
|
|
300
356
|
*/
|
|
301
357
|
@api
|
|
302
358
|
get hideCheckboxColumn() {
|
|
303
|
-
return this.
|
|
359
|
+
return this.state.hideCheckboxColumn;
|
|
304
360
|
}
|
|
305
361
|
|
|
306
|
-
set
|
|
362
|
+
set hideCheckboxColumn(value) {
|
|
307
363
|
const { state } = this;
|
|
364
|
+
const normalizedValue = normalizeBoolean(value);
|
|
308
365
|
|
|
309
|
-
this._columnWidthManager.
|
|
310
|
-
|
|
311
|
-
|
|
366
|
+
this._columnWidthManager.handleCheckboxColumnChange(
|
|
367
|
+
state.hideCheckboxColumn,
|
|
368
|
+
normalizedValue,
|
|
312
369
|
getColumns(state)
|
|
313
370
|
);
|
|
314
371
|
|
|
315
|
-
|
|
372
|
+
this.state.hideCheckboxColumn = normalizedValue;
|
|
373
|
+
// update the columns metadata again to update the status.
|
|
316
374
|
this.updateColumns(this._columns);
|
|
317
375
|
}
|
|
318
376
|
|
|
319
377
|
/**
|
|
320
|
-
* If present, the
|
|
378
|
+
* If present, the table header is hidden.
|
|
321
379
|
* @type {boolean}
|
|
322
380
|
* @default false
|
|
323
381
|
*/
|
|
324
382
|
@api
|
|
325
|
-
get
|
|
326
|
-
return
|
|
383
|
+
get hideTableHeader() {
|
|
384
|
+
return this.state.hideTableHeader;
|
|
327
385
|
}
|
|
328
386
|
|
|
329
|
-
set
|
|
330
|
-
|
|
331
|
-
setRowNumberOffset(state, value);
|
|
332
|
-
|
|
333
|
-
this._columnWidthManager.handleRowNumberOffsetChange(state, widthsData);
|
|
387
|
+
set hideTableHeader(value) {
|
|
388
|
+
this.state.hideTableHeader = normalizeBoolean(value);
|
|
334
389
|
}
|
|
335
390
|
|
|
336
391
|
/**
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
* @
|
|
340
|
-
* @default 0
|
|
392
|
+
* If present, a spinner is shown to indicate that more data is loading.
|
|
393
|
+
* @type {boolean}
|
|
394
|
+
* @default false
|
|
341
395
|
*/
|
|
342
396
|
@api
|
|
343
|
-
get
|
|
344
|
-
return
|
|
397
|
+
get isLoading() {
|
|
398
|
+
return isLoading(this.state);
|
|
345
399
|
}
|
|
346
400
|
|
|
347
|
-
set
|
|
348
|
-
|
|
401
|
+
set isLoading(value) {
|
|
402
|
+
setLoading(this.state, value);
|
|
349
403
|
}
|
|
350
404
|
|
|
351
405
|
/**
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
* @
|
|
406
|
+
* Required for better performance.
|
|
407
|
+
* Associates each row with a unique ID.
|
|
408
|
+
* @type {string}
|
|
409
|
+
* @required
|
|
355
410
|
*/
|
|
356
411
|
@api
|
|
357
|
-
get
|
|
358
|
-
return
|
|
412
|
+
get keyField() {
|
|
413
|
+
return getKeyField(this.state);
|
|
359
414
|
}
|
|
360
415
|
|
|
361
|
-
set
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
this.
|
|
416
|
+
set keyField(value) {
|
|
417
|
+
setKeyField(this.state, value);
|
|
418
|
+
setDirtyValues(this.state, this._draftValues);
|
|
419
|
+
this.updateRowsState();
|
|
365
420
|
}
|
|
366
421
|
|
|
367
422
|
/**
|
|
368
|
-
*
|
|
369
|
-
*
|
|
423
|
+
* Determines when to trigger infinite loading based on
|
|
424
|
+
* how many pixels the table's scroll position is from the bottom of the table.
|
|
425
|
+
* The default is 20.
|
|
370
426
|
* @type {number}
|
|
371
|
-
* @default
|
|
427
|
+
* @default 20
|
|
372
428
|
*/
|
|
373
429
|
@api
|
|
374
|
-
get
|
|
375
|
-
return
|
|
430
|
+
get loadMoreOffset() {
|
|
431
|
+
return getLoadMoreOffset(this.state);
|
|
376
432
|
}
|
|
377
433
|
|
|
378
|
-
set
|
|
379
|
-
|
|
380
|
-
setMaxColumnWidth(state, widthsData, value);
|
|
381
|
-
this._columnWidthManager.maxColumnWidth = this.maxColumnWidth;
|
|
434
|
+
set loadMoreOffset(value) {
|
|
435
|
+
setLoadMoreOffset(this.state, value);
|
|
382
436
|
}
|
|
383
437
|
|
|
384
438
|
/**
|
|
@@ -392,175 +446,144 @@ export default class LightningDatatable extends LightningElement {
|
|
|
392
446
|
return getMaxColumnWidth(this.widthsData);
|
|
393
447
|
}
|
|
394
448
|
|
|
395
|
-
set
|
|
396
|
-
|
|
449
|
+
set maxColumnWidth(value) {
|
|
450
|
+
const { state, widthsData } = this;
|
|
451
|
+
setMaxColumnWidth(getColumns(state), widthsData, value);
|
|
452
|
+
this._columnWidthManager.maxColumnWidth = this.maxColumnWidth;
|
|
397
453
|
}
|
|
398
454
|
|
|
399
455
|
/**
|
|
400
|
-
* The
|
|
401
|
-
*
|
|
456
|
+
* The maximum number of rows that can be selected.
|
|
457
|
+
* Checkboxes are used for selection by default,
|
|
458
|
+
* and radio buttons are used when maxRowSelection is 1.
|
|
402
459
|
* @type {number}
|
|
403
|
-
* @default 10px
|
|
404
460
|
*/
|
|
405
461
|
@api
|
|
406
|
-
get
|
|
407
|
-
return
|
|
462
|
+
get maxRowSelection() {
|
|
463
|
+
return getMaxRowSelection(this.state);
|
|
408
464
|
}
|
|
409
465
|
|
|
410
|
-
set
|
|
411
|
-
|
|
412
|
-
|
|
466
|
+
set maxRowSelection(value) {
|
|
467
|
+
const previousSelectionLength = getCurrentSelectionLength(this.state);
|
|
468
|
+
setMaxRowSelection(this.state, value);
|
|
469
|
+
if (previousSelectionLength > 0) {
|
|
470
|
+
this.fireSelectedRowsChange(this.getSelectedRows());
|
|
471
|
+
}
|
|
413
472
|
}
|
|
414
473
|
|
|
415
474
|
/**
|
|
416
|
-
* The
|
|
417
|
-
*
|
|
418
|
-
* @type {
|
|
475
|
+
* The minimum width for all columns.
|
|
476
|
+
* The default is 50px.
|
|
477
|
+
* @type {number}
|
|
478
|
+
* @default 50px
|
|
419
479
|
*/
|
|
420
480
|
@api
|
|
421
|
-
get
|
|
422
|
-
return
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
set sortedDirection(value) {
|
|
426
|
-
setSortedDirection(this.state, value);
|
|
427
|
-
updateSorting(this.state);
|
|
481
|
+
get minColumnWidth() {
|
|
482
|
+
return getMinColumnWidth(this.widthsData);
|
|
428
483
|
}
|
|
429
484
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
* @type {string}
|
|
435
|
-
*/
|
|
436
|
-
@api
|
|
437
|
-
get sortedDirection() {
|
|
438
|
-
return getSortedDirection(this.state);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
set defaultSortDirection(value) {
|
|
442
|
-
setDefaultSortDirection(this.state, value);
|
|
443
|
-
updateSorting(this.state);
|
|
485
|
+
set minColumnWidth(value) {
|
|
486
|
+
const { state, widthsData } = this;
|
|
487
|
+
setMinColumnWidth(getColumns(state), widthsData, value);
|
|
488
|
+
this._columnWidthManager.minColumnWidth = this.minColumnWidth;
|
|
444
489
|
}
|
|
445
490
|
|
|
446
491
|
/**
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
* @
|
|
451
|
-
* @default asc
|
|
492
|
+
* @typedef RenderManagerConfig
|
|
493
|
+
* @type {object}
|
|
494
|
+
* @property {boolean} viewportRendering - Specifies whether to defer rendering of rows outside the viewport until the user begins scrolling. To use this feature, create a fixed-height container element for lightning-datatable.
|
|
495
|
+
* @property {number} rowHeight - Specifies the height of a row, in px
|
|
452
496
|
*/
|
|
453
|
-
@api
|
|
454
|
-
get defaultSortDirection() {
|
|
455
|
-
return getDefaultSortDirection(this.state);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
set enableInfiniteLoading(value) {
|
|
459
|
-
setInfiniteLoading(this.state, value);
|
|
460
|
-
}
|
|
461
497
|
|
|
462
498
|
/**
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
* @type {
|
|
467
|
-
* @default false
|
|
499
|
+
* Reserved for internal use.
|
|
500
|
+
* Enables and configures advanced rendering modes.
|
|
501
|
+
*
|
|
502
|
+
* @type {RenderManagerConfig} value - config object for datatable rendering
|
|
468
503
|
*/
|
|
469
504
|
@api
|
|
470
|
-
get
|
|
471
|
-
return
|
|
505
|
+
get renderConfig() {
|
|
506
|
+
return this._renderConfig;
|
|
472
507
|
}
|
|
473
508
|
|
|
474
|
-
set
|
|
475
|
-
|
|
509
|
+
set renderConfig(value) {
|
|
510
|
+
if (typeof value === 'object' && !isIE11) {
|
|
511
|
+
const enableViewportRendering = value.viewportRendering;
|
|
512
|
+
setViewportRendering(this.state, enableViewportRendering);
|
|
513
|
+
|
|
514
|
+
this._renderManager.configure(this, value);
|
|
515
|
+
this._renderConfig = value;
|
|
516
|
+
}
|
|
476
517
|
}
|
|
477
518
|
|
|
478
519
|
/**
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
*
|
|
483
|
-
|
|
520
|
+
* Allows developer to opt-in to a role-based table.
|
|
521
|
+
* Allowed options - "role-based" or "default"
|
|
522
|
+
* `role-based` -> Renders <div>
|
|
523
|
+
* `default` -> Renders <table>
|
|
524
|
+
*/
|
|
525
|
+
/**
|
|
526
|
+
* Reserved for internal use.
|
|
484
527
|
*/
|
|
485
528
|
@api
|
|
486
|
-
get
|
|
487
|
-
return
|
|
529
|
+
get renderMode() {
|
|
530
|
+
return this._renderMode;
|
|
488
531
|
}
|
|
489
532
|
|
|
490
|
-
set
|
|
491
|
-
|
|
533
|
+
set renderMode(value) {
|
|
534
|
+
this._renderMode = normalizeString(value, {
|
|
535
|
+
fallbackValue: 'default',
|
|
536
|
+
validValues: ['default', 'role-based'],
|
|
537
|
+
});
|
|
538
|
+
this.state.renderModeRoleBased = this._renderMode === 'role-based';
|
|
539
|
+
updateCellClassForRoleBasedMode(this.state);
|
|
492
540
|
}
|
|
493
541
|
|
|
494
542
|
/**
|
|
495
|
-
* If present,
|
|
543
|
+
* If present, column resizing is disabled.
|
|
496
544
|
* @type {boolean}
|
|
497
545
|
* @default false
|
|
498
546
|
*/
|
|
499
547
|
@api
|
|
500
|
-
get
|
|
501
|
-
return
|
|
548
|
+
get resizeColumnDisabled() {
|
|
549
|
+
return isResizeColumnDisabled(this.widthsData);
|
|
502
550
|
}
|
|
503
551
|
|
|
504
|
-
set
|
|
505
|
-
|
|
506
|
-
const enableViewportRendering = value.viewportRendering;
|
|
507
|
-
setViewportRendering(this.state, enableViewportRendering);
|
|
508
|
-
|
|
509
|
-
this._renderManager.configure(this, value);
|
|
510
|
-
this._renderConfig = value;
|
|
511
|
-
}
|
|
552
|
+
set resizeColumnDisabled(value) {
|
|
553
|
+
setResizeColumnDisabled(this.widthsData, value);
|
|
512
554
|
}
|
|
513
555
|
|
|
514
556
|
/**
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
* @
|
|
518
|
-
* @
|
|
519
|
-
*/
|
|
520
|
-
|
|
521
|
-
/**
|
|
522
|
-
* Reserved for internal use.
|
|
523
|
-
* Enables and configures advanced rendering modes.
|
|
524
|
-
*
|
|
525
|
-
* @type {RenderManagerConfig} value - config object for datatable rendering
|
|
557
|
+
* The width to resize the column when a user presses left or right arrow.
|
|
558
|
+
* The default is 10px.
|
|
559
|
+
* @type {number}
|
|
560
|
+
* @default 10px
|
|
526
561
|
*/
|
|
527
562
|
@api
|
|
528
|
-
get
|
|
529
|
-
return this.
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
get viewportRendering() {
|
|
533
|
-
return isViewportRenderingEnabled(this.state);
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
get renderedRows() {
|
|
537
|
-
if (this.viewportRendering && !isIE11) {
|
|
538
|
-
return this.state.rows.slice(0, this._renderedRowCount);
|
|
539
|
-
}
|
|
540
|
-
return this.state.rows;
|
|
563
|
+
get resizeStep() {
|
|
564
|
+
return getResizeStep(this.widthsData);
|
|
541
565
|
}
|
|
542
566
|
|
|
543
|
-
set
|
|
544
|
-
|
|
545
|
-
setMaxRowSelection(this.state, value);
|
|
546
|
-
if (previousSelectionLenght > 0) {
|
|
547
|
-
this.fireSelectedRowsChange(this.getSelectedRows());
|
|
548
|
-
}
|
|
567
|
+
set resizeStep(value) {
|
|
568
|
+
setResizeStep(this.widthsData, value);
|
|
549
569
|
}
|
|
550
570
|
|
|
551
571
|
/**
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
* and radio buttons are used when maxRowSelection is 1.
|
|
572
|
+
* Determines where to start counting the row number.
|
|
573
|
+
* The default is 0.
|
|
555
574
|
* @type {number}
|
|
575
|
+
* @default 0
|
|
556
576
|
*/
|
|
557
577
|
@api
|
|
558
|
-
get
|
|
559
|
-
return
|
|
578
|
+
get rowNumberOffset() {
|
|
579
|
+
return getRowNumberOffset(this.state);
|
|
560
580
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
this
|
|
581
|
+
|
|
582
|
+
set rowNumberOffset(value) {
|
|
583
|
+
const { state, widthsData } = this;
|
|
584
|
+
setRowNumberOffset(state, value);
|
|
585
|
+
|
|
586
|
+
this._columnWidthManager.handleRowNumberOffsetChange(state, widthsData);
|
|
564
587
|
}
|
|
565
588
|
|
|
566
589
|
/**
|
|
@@ -572,66 +595,63 @@ export default class LightningDatatable extends LightningElement {
|
|
|
572
595
|
return getSelectedRowsKeys(this.state);
|
|
573
596
|
}
|
|
574
597
|
|
|
575
|
-
set
|
|
576
|
-
|
|
577
|
-
this.
|
|
598
|
+
set selectedRows(value) {
|
|
599
|
+
this._customerSelectedRows = value;
|
|
600
|
+
this.setSelectedRows(value);
|
|
578
601
|
}
|
|
579
602
|
|
|
580
603
|
/**
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
* @
|
|
604
|
+
* If present, the row numbers are shown in the first column.
|
|
605
|
+
* @type {boolean}
|
|
606
|
+
* @default false
|
|
584
607
|
*/
|
|
585
608
|
@api
|
|
586
|
-
get
|
|
587
|
-
return
|
|
609
|
+
get showRowNumberColumn() {
|
|
610
|
+
return hasRowNumberColumn(this.state);
|
|
588
611
|
}
|
|
589
612
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
* @type {object}
|
|
593
|
-
*/
|
|
594
|
-
@api
|
|
595
|
-
get draftValues() {
|
|
596
|
-
return getDirtyValues(this.state);
|
|
597
|
-
}
|
|
613
|
+
set showRowNumberColumn(value) {
|
|
614
|
+
const { state, _columns } = this;
|
|
598
615
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
616
|
+
this._columnWidthManager.handleRowNumberColumnChange(
|
|
617
|
+
getRowNumberOffset(state),
|
|
618
|
+
value,
|
|
619
|
+
getColumns(state)
|
|
620
|
+
);
|
|
602
621
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
}
|
|
622
|
+
setShowRowNumberColumn(state, value);
|
|
623
|
+
this.updateColumns(_columns);
|
|
606
624
|
}
|
|
607
625
|
|
|
608
626
|
/**
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
* @
|
|
627
|
+
* The column key or fieldName that controls the sorting order.
|
|
628
|
+
* Sort the data using the onsort event handler.
|
|
629
|
+
* @type {string}
|
|
612
630
|
*/
|
|
613
631
|
@api
|
|
614
|
-
get
|
|
615
|
-
return this.state
|
|
632
|
+
get sortedBy() {
|
|
633
|
+
return getSortedBy(this.state);
|
|
616
634
|
}
|
|
617
635
|
|
|
618
|
-
set
|
|
619
|
-
this.state
|
|
636
|
+
set sortedBy(value) {
|
|
637
|
+
setSortedBy(this.state, value);
|
|
638
|
+
updateSorting(this.state);
|
|
620
639
|
}
|
|
621
640
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
return
|
|
641
|
+
/**
|
|
642
|
+
* Specifies the sorting direction.
|
|
643
|
+
* Sort the data using the onsort event handler.
|
|
644
|
+
* Valid options include 'asc' and 'desc'.
|
|
645
|
+
* @type {string}
|
|
646
|
+
*/
|
|
647
|
+
@api
|
|
648
|
+
get sortedDirection() {
|
|
649
|
+
return getSortedDirection(this.state);
|
|
631
650
|
}
|
|
632
651
|
|
|
633
|
-
|
|
634
|
-
|
|
652
|
+
set sortedDirection(value) {
|
|
653
|
+
setSortedDirection(this.state, value);
|
|
654
|
+
updateSorting(this.state);
|
|
635
655
|
}
|
|
636
656
|
|
|
637
657
|
/**
|
|
@@ -641,50 +661,298 @@ export default class LightningDatatable extends LightningElement {
|
|
|
641
661
|
*/
|
|
642
662
|
@api
|
|
643
663
|
get suppressBottomBar() {
|
|
644
|
-
return this.
|
|
664
|
+
return this._suppressBottomBar;
|
|
645
665
|
}
|
|
646
666
|
|
|
647
667
|
set suppressBottomBar(value) {
|
|
648
|
-
this.
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
set columnWidthsMode(value) {
|
|
652
|
-
const normalizedValue = normalizeString(value, {
|
|
653
|
-
fallbackValue: 'fixed',
|
|
654
|
-
validValues: ['fixed', 'auto'],
|
|
655
|
-
});
|
|
656
|
-
this._columnWidthManager.columnWidthMode = normalizedValue;
|
|
657
|
-
|
|
658
|
-
const { state, widthsData } = this;
|
|
659
|
-
if (widthsData.columnWidthsMode !== normalizedValue) {
|
|
660
|
-
this._columnWidthManager.handleWidthModeChange(getColumns(state));
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
widthsData.columnWidthsMode = normalizedValue;
|
|
668
|
+
this._suppressBottomBar = normalizeBoolean(value);
|
|
664
669
|
}
|
|
665
670
|
|
|
666
671
|
/**
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
*
|
|
670
|
-
* @
|
|
672
|
+
* This value specifies the number of lines after which the
|
|
673
|
+
* content will be cut off and hidden. It must be at least 1 or more.
|
|
674
|
+
* The text in the last line is truncated and shown with an ellipsis.
|
|
675
|
+
* @type {integer}
|
|
671
676
|
*/
|
|
672
677
|
@api
|
|
673
|
-
get
|
|
674
|
-
return this.
|
|
678
|
+
get wrapTextMaxLines() {
|
|
679
|
+
return this.state.wrapTextMaxLines;
|
|
675
680
|
}
|
|
676
681
|
|
|
677
|
-
|
|
678
|
-
const {
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
handleSelectionCellClick,
|
|
684
|
-
} = this;
|
|
682
|
+
set wrapTextMaxLines(value) {
|
|
683
|
+
const { state } = this;
|
|
684
|
+
setWrapTextMaxLines(state, value);
|
|
685
|
+
this._columnWidthManager.wrapTextMaxLines = state.wrapTextMaxLines;
|
|
686
|
+
this.updateRowsAndCellIndexes(state);
|
|
687
|
+
}
|
|
685
688
|
|
|
686
|
-
|
|
687
|
-
|
|
689
|
+
/************************** PUBLIC METHODS ***************************/
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Returns data in each selected row.
|
|
693
|
+
* @returns {array} An array of data in each selected row.
|
|
694
|
+
*/
|
|
695
|
+
@api
|
|
696
|
+
getSelectedRows() {
|
|
697
|
+
const data = unwrap(getData(this.state));
|
|
698
|
+
return this.state.rows.reduce((prev, row, index) => {
|
|
699
|
+
if (row.isSelected) {
|
|
700
|
+
prev.push(data[index]);
|
|
701
|
+
}
|
|
702
|
+
return prev;
|
|
703
|
+
}, []);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Opens the inline edit panel for the datatable's currently active cell. If the active cell is not
|
|
708
|
+
* editable, then the panel is instead opened for the first editable cell in the table. Given two
|
|
709
|
+
* distinct cells, C_x and C_y, C_x is considered "first" in the cell ordering if the following condition
|
|
710
|
+
* evaluates to true:
|
|
711
|
+
*
|
|
712
|
+
* (C_x.rowIndex < C_y.rowIndex) || (C_x.rowIndex === C_y.rowIndex && C_x.columnIndex < C_y.columnIndex)
|
|
713
|
+
*
|
|
714
|
+
* If there is no data in the table or there are no editable cells in the table then calling this function
|
|
715
|
+
* results in a no-op.
|
|
716
|
+
*/
|
|
717
|
+
@api
|
|
718
|
+
openInlineEdit() {
|
|
719
|
+
openInlineEditOnActiveCell(this);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/************************** PRIVATE GETTERS **************************/
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Retrieves the grid container:
|
|
726
|
+
* 1. For a table-based table, it will retrieve the <table role="grid"> element
|
|
727
|
+
* 2. For a role-based table, it will retrieve the <div role="grid"> element
|
|
728
|
+
* 3. If it is a tree grid, it will retrieve the <table role="treegrid"> element
|
|
729
|
+
*/
|
|
730
|
+
get gridContainer() {
|
|
731
|
+
return (
|
|
732
|
+
this.template.querySelector('[role="grid"]') ||
|
|
733
|
+
this.template.querySelector('[role="treegrid"]')
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
get computedTableContainerClass() {
|
|
738
|
+
return classSet({
|
|
739
|
+
'slds-table_header-fixed_container': !this.hideTableHeader,
|
|
740
|
+
'slds-scrollable_x': !this._isResizing,
|
|
741
|
+
}).toString();
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
get computedTableClass() {
|
|
745
|
+
const headerType = this.hideTableHeader ? 'hidden' : 'fixed';
|
|
746
|
+
return classSet(
|
|
747
|
+
`slds-table slds-table_header-${headerType} slds-table_bordered slds-table_edit`
|
|
748
|
+
)
|
|
749
|
+
.add({
|
|
750
|
+
'slds-table_resizable-cols': this.hasResizebleColumns,
|
|
751
|
+
'slds-tree slds-table_tree': hasTreeDataType(this.state),
|
|
752
|
+
})
|
|
753
|
+
.toString();
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
get computedTableRole() {
|
|
757
|
+
return hasTreeDataType(this.state) ? 'treegrid' : 'grid';
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
get computedTableStyle() {
|
|
761
|
+
if (this._columnWidthManager.isAutoResizingUpdateQueued()) {
|
|
762
|
+
return ['table-layout:auto'].join(';');
|
|
763
|
+
}
|
|
764
|
+
return [
|
|
765
|
+
'table-layout:fixed',
|
|
766
|
+
getCSSWidthStyleOfTable(this.widthsData),
|
|
767
|
+
].join(';');
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
get computedTbodyStyle() {
|
|
771
|
+
if (
|
|
772
|
+
hasRowNumberColumn(this.state) &&
|
|
773
|
+
getRowNumberOffset(this.state) >= 0
|
|
774
|
+
) {
|
|
775
|
+
return (
|
|
776
|
+
'counter-reset: row-number ' + getRowNumberOffset(this.state)
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
return '';
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Sets the min height and the table width on the container
|
|
784
|
+
* that wraps [role="grid"].
|
|
785
|
+
* 1. Min Height is required for the case when the header actions
|
|
786
|
+
* dropdown is opened and there are no rows present. The dropdown
|
|
787
|
+
* would be cut off. To prevent that, we set a min height on the table.
|
|
788
|
+
* 2. The table width is required for horizontal scroll. If the table
|
|
789
|
+
* is overflowing horizontally, we need to set the width in order
|
|
790
|
+
* to be able to view the remaining columns on scroll.
|
|
791
|
+
*/
|
|
792
|
+
get computedScrollerStyle() {
|
|
793
|
+
const minHeight = this._actionsMinHeightStyle
|
|
794
|
+
? `${this._actionsMinHeightStyle};`
|
|
795
|
+
: '';
|
|
796
|
+
if (this._columnWidthManager.isAutoResizingUpdateQueued()) {
|
|
797
|
+
return `${minHeight}overflow-x:auto`;
|
|
798
|
+
}
|
|
799
|
+
return `${minHeight}${getCSSWidthStyleOfTable(this.widthsData)}`;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
get scrollerXStyles() {
|
|
803
|
+
const styles = {
|
|
804
|
+
height: '100%',
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
if (this.showStatusBar) {
|
|
808
|
+
styles['padding-bottom'] = '3rem';
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
if (this._columnWidthManager.isAutoResizingUpdateQueued()) {
|
|
812
|
+
styles['overflow-x'] = 'auto';
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
return Object.entries(styles)
|
|
816
|
+
.map(([key, value]) => key + ':' + value)
|
|
817
|
+
.join(';');
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Private method to get datatable header element
|
|
822
|
+
* used when getting checkboxColumnHeaderId for
|
|
823
|
+
* aria-labelledby in checkbox column
|
|
824
|
+
* @returns {(HTMLElement|null)}
|
|
825
|
+
*/
|
|
826
|
+
get checkboxColumnHeaderElement() {
|
|
827
|
+
return this.template.querySelector(
|
|
828
|
+
'lightning-primitive-header-factory'
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* Private method to get computedCheckboxColumnHeaderId
|
|
834
|
+
* from checkboxColumnHeaderElement for
|
|
835
|
+
* aria-labelledby in checkbox column
|
|
836
|
+
*/
|
|
837
|
+
get computedCheckboxColumnHeaderId() {
|
|
838
|
+
return this.checkboxColumnHeaderElement
|
|
839
|
+
? this.checkboxColumnHeaderElement.computedColumnHeaderId
|
|
840
|
+
: null;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
get computedAriaLiveClassForNavMode() {
|
|
844
|
+
const keyboardMode = this.state.keyboardMode;
|
|
845
|
+
return classSet()
|
|
846
|
+
.add({
|
|
847
|
+
'slds-hide': keyboardMode !== 'NAVIGATION',
|
|
848
|
+
'slds-assistive-text': keyboardMode === 'NAVIGATION',
|
|
849
|
+
})
|
|
850
|
+
.toString();
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
get computedAriaLiveClassForActionMode() {
|
|
854
|
+
const keyboardMode = this.state.keyboardMode;
|
|
855
|
+
return classSet()
|
|
856
|
+
.add({
|
|
857
|
+
'slds-hide': keyboardMode !== 'ACTION',
|
|
858
|
+
'slds-assistive-text': keyboardMode === 'ACTION',
|
|
859
|
+
})
|
|
860
|
+
.toString();
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* aria-rowcount is the count of TRs in the table
|
|
865
|
+
* It includes the # of rows of data + column header row (since this is also a TR)
|
|
866
|
+
* A table with no rows of data still has an aria-rowcount of 1
|
|
867
|
+
*/
|
|
868
|
+
get ariaRowCount() {
|
|
869
|
+
return this.state.rows.length + 1;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
get hasValidKeyField() {
|
|
873
|
+
if (hasValidKeyField(this.state)) {
|
|
874
|
+
return true;
|
|
875
|
+
}
|
|
876
|
+
// eslint-disable-next-line no-console
|
|
877
|
+
console.error(
|
|
878
|
+
`The "keyField" is a required attribute of lightning:datatable.`
|
|
879
|
+
);
|
|
880
|
+
return false;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
get numberOfColumns() {
|
|
884
|
+
return getColumns(this.state).length;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
get hasResizebleColumns() {
|
|
888
|
+
return !isResizeColumnDisabled(this.widthsData);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
get privateTypes() {
|
|
892
|
+
return this._privateTypes;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
get viewportRendering() {
|
|
896
|
+
return isViewportRenderingEnabled(this.state);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
get renderedRows() {
|
|
900
|
+
if (this.viewportRendering && !isIE11) {
|
|
901
|
+
return this.state.rows.slice(0, this._renderedRowCount);
|
|
902
|
+
}
|
|
903
|
+
return this.state.rows;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
get showSelectAllCheckbox() {
|
|
907
|
+
return !getHideSelectAllCheckbox(this.state);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
get showStatusBar() {
|
|
911
|
+
return isInlineEditTriggered(this.state) && !this.suppressBottomBar;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
get tableError() {
|
|
915
|
+
return getTableError(this.state);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
get i18n() {
|
|
919
|
+
return i18n;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/************************** LIFECYCLE HOOKS **************************/
|
|
923
|
+
|
|
924
|
+
/**
|
|
925
|
+
* Initialize the following:
|
|
926
|
+
* 1. DatatableTypes
|
|
927
|
+
* 2. ColumnWidthManager
|
|
928
|
+
* 3. RenderManager
|
|
929
|
+
*/
|
|
930
|
+
constructor() {
|
|
931
|
+
super();
|
|
932
|
+
|
|
933
|
+
this._privateTypes = new DatatableTypes(this.constructor.customTypes);
|
|
934
|
+
|
|
935
|
+
this._columnWidthManager = new ColumnWidthManager(this.widthsData);
|
|
936
|
+
this.updateRowsAndCellIndexes = updateRowsAndCellIndexes.bind(this);
|
|
937
|
+
|
|
938
|
+
this._renderManager = new RenderManager();
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/**
|
|
942
|
+
* Attach event handlers for various events on `lightning-datatable`
|
|
943
|
+
*/
|
|
944
|
+
connectedCallback() {
|
|
945
|
+
const {
|
|
946
|
+
handleResizeColumn,
|
|
947
|
+
handleUpdateColumnSort,
|
|
948
|
+
handleCellFocusByClick,
|
|
949
|
+
handleFalseCellBlur,
|
|
950
|
+
handleSelectionCellClick,
|
|
951
|
+
} = this;
|
|
952
|
+
|
|
953
|
+
// Row Selection and De-selection
|
|
954
|
+
this.template.addEventListener(
|
|
955
|
+
'selectallrows',
|
|
688
956
|
handleSelectionCellClick.bind(this)
|
|
689
957
|
);
|
|
690
958
|
this.template.addEventListener(
|
|
@@ -705,18 +973,22 @@ export default class LightningDatatable extends LightningElement {
|
|
|
705
973
|
handleRowSelectionChange.bind(this)
|
|
706
974
|
);
|
|
707
975
|
|
|
976
|
+
// Column Resizing
|
|
708
977
|
this.template.addEventListener(
|
|
709
978
|
'resizecol',
|
|
710
979
|
handleResizeColumn.bind(this)
|
|
711
980
|
);
|
|
981
|
+
|
|
982
|
+
// Column Sorting
|
|
712
983
|
this.template.addEventListener(
|
|
713
984
|
'privateupdatecolsort',
|
|
714
985
|
handleUpdateColumnSort.bind(this)
|
|
715
986
|
);
|
|
716
987
|
|
|
988
|
+
// Cell Interaction
|
|
717
989
|
this.template.addEventListener(
|
|
718
990
|
'privatecellkeydown',
|
|
719
|
-
|
|
991
|
+
handleKeydownOnCell.bind(this)
|
|
720
992
|
);
|
|
721
993
|
|
|
722
994
|
this.template.addEventListener(
|
|
@@ -728,7 +1000,7 @@ export default class LightningDatatable extends LightningElement {
|
|
|
728
1000
|
handleFalseCellBlur.bind(this)
|
|
729
1001
|
);
|
|
730
1002
|
|
|
731
|
-
//
|
|
1003
|
+
// Row Level Actions
|
|
732
1004
|
this.template.addEventListener(
|
|
733
1005
|
'privatecellactiontriggered',
|
|
734
1006
|
handleRowActionTriggered.bind(this)
|
|
@@ -742,7 +1014,7 @@ export default class LightningDatatable extends LightningElement {
|
|
|
742
1014
|
handleCellButtonClick.bind(this)
|
|
743
1015
|
);
|
|
744
1016
|
|
|
745
|
-
//
|
|
1017
|
+
// Header Actions
|
|
746
1018
|
this.template.addEventListener(
|
|
747
1019
|
'privatecellheaderactionmenuopening',
|
|
748
1020
|
handleHeaderActionMenuOpening.bind(this)
|
|
@@ -756,75 +1028,41 @@ export default class LightningDatatable extends LightningElement {
|
|
|
756
1028
|
handleHeaderActionTriggered.bind(this)
|
|
757
1029
|
);
|
|
758
1030
|
|
|
759
|
-
//
|
|
1031
|
+
// Inline Edit
|
|
760
1032
|
this.template.addEventListener(
|
|
761
1033
|
'privateeditcell',
|
|
762
1034
|
handleEditCell.bind(this)
|
|
763
1035
|
);
|
|
764
1036
|
}
|
|
765
1037
|
|
|
1038
|
+
/**
|
|
1039
|
+
* Renders the appropriate template - div.html or table.html,
|
|
1040
|
+
* based on the `render-mode` value passed in.
|
|
1041
|
+
* By default, table.html is rendered
|
|
1042
|
+
*/
|
|
766
1043
|
render() {
|
|
767
|
-
return
|
|
1044
|
+
return this.state.renderModeRoleBased ? divTemplate : tableTemplate;
|
|
768
1045
|
}
|
|
769
1046
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
if (
|
|
773
|
-
this.state.keyboardMode === 'NAVIGATION' &&
|
|
774
|
-
this.state.rowMode === true
|
|
775
|
-
) {
|
|
776
|
-
event.stopPropagation();
|
|
777
|
-
|
|
778
|
-
const tr = event.currentTarget;
|
|
779
|
-
const rowKeyValue = tr.getAttribute('data-row-key-value');
|
|
780
|
-
const keyCode = event.keyCode;
|
|
781
|
-
const rowHasChildren = !!tr.getAttribute('aria-expanded');
|
|
782
|
-
const rowExpanded = tr.getAttribute('aria-expanded') === 'true';
|
|
783
|
-
const rowLevel = tr.getAttribute('aria-level');
|
|
1047
|
+
renderedCallback() {
|
|
1048
|
+
const { state, template, widthsData } = this;
|
|
784
1049
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
rowExpanded,
|
|
792
|
-
rowLevel,
|
|
793
|
-
keyEvent: event,
|
|
794
|
-
},
|
|
795
|
-
};
|
|
1050
|
+
// This keeps underlying table element up to date if the aria-* properties on this element is dynamically changed.
|
|
1051
|
+
// It does the work of removing and adding the attribute if the value is empty(ish) or a normal string.
|
|
1052
|
+
synchronizeAttrs(this.gridContainer, {
|
|
1053
|
+
'aria-label': this.ariaLabel,
|
|
1054
|
+
'aria-labelledby': this.ariaLabelledBy,
|
|
1055
|
+
});
|
|
796
1056
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
disconnectedCallback() {
|
|
802
|
-
if (this.privateWidthObserver) {
|
|
803
|
-
this.privateWidthObserver.disconnect();
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
this._renderManager.disconnectResizeObserver();
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
renderedCallback() {
|
|
810
|
-
const { state, template, widthsData } = this;
|
|
811
|
-
|
|
812
|
-
// This keeps underlying table element up to date if the aria-* properties on this element is dynamically changed.
|
|
813
|
-
// It does the work of removing and adding the attribute if the value is empty(ish) or a normal string.
|
|
814
|
-
synchronizeAttrs(this.template.querySelector('table'), {
|
|
815
|
-
'aria-label': this.ariaLabel,
|
|
816
|
-
'aria-labelledby': this.ariaLabelledBy,
|
|
817
|
-
});
|
|
818
|
-
|
|
819
|
-
if (!this.privateWidthObserver) {
|
|
820
|
-
this.privateWidthObserver = new LightningDatatableResizeObserver(
|
|
1057
|
+
if (!this._privateWidthObserver) {
|
|
1058
|
+
this._privateWidthObserver = new LightningDatatableResizeObserver(
|
|
821
1059
|
template,
|
|
822
1060
|
state,
|
|
823
1061
|
widthsData,
|
|
824
1062
|
this._columnWidthManager
|
|
825
1063
|
);
|
|
826
|
-
} else if (!this.
|
|
827
|
-
this.
|
|
1064
|
+
} else if (!this._privateWidthObserver.isConnected()) {
|
|
1065
|
+
this._privateWidthObserver.observe(template);
|
|
828
1066
|
}
|
|
829
1067
|
|
|
830
1068
|
if (this._columnWidthManager.isResizingUpdateQueued()) {
|
|
@@ -845,9 +1083,15 @@ export default class LightningDatatable extends LightningElement {
|
|
|
845
1083
|
}
|
|
846
1084
|
}
|
|
847
1085
|
|
|
1086
|
+
// Managing the cell widths is only required for the role-based table
|
|
1087
|
+
if (state.renderModeRoleBased) {
|
|
1088
|
+
// TODO: Look to further optimize - Do this only when required
|
|
1089
|
+
recomputeCellStyles(this.privateTypes, state);
|
|
1090
|
+
}
|
|
1091
|
+
|
|
848
1092
|
handlePrefetch.call(this, template, state);
|
|
849
1093
|
// customerSelectedRows is only valid till render, after it, the one used should be the one from the state.
|
|
850
|
-
this.
|
|
1094
|
+
this._customerSelectedRows = null;
|
|
851
1095
|
// set the previous focused cell to null after render is done
|
|
852
1096
|
resetCellToFocusFromPrev(state);
|
|
853
1097
|
|
|
@@ -866,256 +1110,77 @@ export default class LightningDatatable extends LightningElement {
|
|
|
866
1110
|
}
|
|
867
1111
|
}
|
|
868
1112
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
updateRowsState() {
|
|
875
|
-
const { state, widthsData, template } = this;
|
|
876
|
-
// calculate cell to focus next before indexes are updated
|
|
877
|
-
setCellToFocusFromPrev(state, template);
|
|
878
|
-
|
|
879
|
-
this.updateRowsAndCellIndexes(state);
|
|
880
|
-
|
|
881
|
-
if (this.viewportRendering) {
|
|
882
|
-
this._renderManager.updateViewportRendering(this);
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
this._columnWidthManager.handleRowNumberOffsetChange(state, widthsData);
|
|
886
|
-
// update celltofocus next to null if the row still exists after indexes calculation
|
|
887
|
-
updateCellToFocusFromPrev(state);
|
|
888
|
-
syncSelectedRowsKeys(state, this.getSelectedRows()).ifChanged(() => {
|
|
889
|
-
// Only trigger row selection event once after all the setters have executed
|
|
890
|
-
// Otherwise, event can be fired with stale data if not all setters have been triggered
|
|
891
|
-
if (!this._rowSelectionEventPending) {
|
|
892
|
-
this._rowSelectionEventPending = true;
|
|
893
|
-
Promise.resolve().then(() => {
|
|
894
|
-
if (this._rowSelectionEventPending) {
|
|
895
|
-
this.fireSelectedRowsChange(this.getSelectedRows());
|
|
896
|
-
this._rowSelectionEventPending = false;
|
|
897
|
-
}
|
|
898
|
-
});
|
|
899
|
-
}
|
|
900
|
-
});
|
|
901
|
-
syncActiveCell(state);
|
|
902
|
-
|
|
903
|
-
if (state.keyboardMode === 'NAVIGATION') {
|
|
904
|
-
updateTabIndexActiveCell(state);
|
|
905
|
-
updateTabIndexActiveRow(state);
|
|
906
|
-
}
|
|
907
|
-
// if there is previously focused cell which was deleted set focus from celltofocus next
|
|
908
|
-
if (state.cellToFocusNext && state.activeCell) {
|
|
909
|
-
setFocusActiveCell(this.template, this.state);
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
updateColumns(columns) {
|
|
914
|
-
const { state, widthsData, template } = this;
|
|
915
|
-
const hadTreeDataTypePreviously = hasTreeDataType(state);
|
|
916
|
-
// calculate cell to focus next before indexes are updated
|
|
917
|
-
setCellToFocusFromPrev(state, template);
|
|
918
|
-
normalizeColumns(state, columns, this.privateTypes);
|
|
919
|
-
setDirtyValues(state, this._draftValues);
|
|
920
|
-
updateRowNavigationMode(hadTreeDataTypePreviously, state);
|
|
921
|
-
state.headerIndexes = generateHeaderIndexes(getColumns(state));
|
|
922
|
-
// Updates state.wrapText and when isWrapableType, sets internal header actions
|
|
923
|
-
updateHeaderActions(state);
|
|
924
|
-
this.updateRowsAndCellIndexes(state);
|
|
925
|
-
updateSelectionState(state);
|
|
926
|
-
this._columnWidthManager.handleRowNumberOffsetChange(state, widthsData);
|
|
927
|
-
updateColumnWidthsMetadata(state, widthsData);
|
|
928
|
-
// set the celltofocus next to null if the column still exists after indexes calculation
|
|
929
|
-
updateCellToFocusFromPrev(state);
|
|
930
|
-
|
|
931
|
-
if (getColumns(state).length !== getColumnsWidths(widthsData).length) {
|
|
932
|
-
if (getData(state).length > 0) {
|
|
933
|
-
// when there are column changes, update the active cell
|
|
934
|
-
syncActiveCell(state);
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
if (state.keyboardMode === 'NAVIGATION') {
|
|
938
|
-
updateTabIndexActiveCell(state);
|
|
939
|
-
updateTabIndexActiveRow(state);
|
|
940
|
-
}
|
|
941
|
-
// if there is previously focused cell which was deleted set focus from celltofocus next
|
|
942
|
-
if (state.cellToFocusNext && state.activeCell) {
|
|
943
|
-
setFocusActiveCell(this.template, this.state);
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
get computedTableHeaderClass() {
|
|
948
|
-
if (this.state.hideTableHeader) {
|
|
949
|
-
return 'slds-assistive-text';
|
|
950
|
-
}
|
|
951
|
-
return undefined;
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
// Min height required while actions menu is opened
|
|
955
|
-
_actionsMinHeightStyle = '';
|
|
956
|
-
|
|
957
|
-
get computedScrollerStyle() {
|
|
958
|
-
const minHeight = this._actionsMinHeightStyle
|
|
959
|
-
? `${this._actionsMinHeightStyle};`
|
|
960
|
-
: '';
|
|
961
|
-
if (this._columnWidthManager.isAutoResizingUpdateQueued()) {
|
|
962
|
-
return `${minHeight}overflow-x:auto`;
|
|
963
|
-
}
|
|
964
|
-
return `${minHeight}${getTableWidthStyle(this.widthsData)}`;
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
get computedTableContainerClass() {
|
|
968
|
-
return classSet({
|
|
969
|
-
'slds-table_header-fixed_container': !this.hideTableHeader,
|
|
970
|
-
})
|
|
971
|
-
.add({ 'slds-scrollable_x': !this._isResizing })
|
|
972
|
-
.toString();
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
get computedTableClass() {
|
|
976
|
-
const headerType = this.hideTableHeader ? 'hidden' : 'fixed';
|
|
977
|
-
return classSet(
|
|
978
|
-
`slds-table slds-table_header-${headerType} slds-table_bordered slds-table_edit`
|
|
979
|
-
)
|
|
980
|
-
.add({ 'slds-table_resizable-cols': this.hasResizebleColumns })
|
|
981
|
-
.add({ 'slds-tree slds-table_tree': hasTreeDataType(this.state) })
|
|
982
|
-
.toString();
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
get computedTableRole() {
|
|
986
|
-
return hasTreeDataType(this.state) ? 'treegrid' : 'grid';
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
get computedTableStyle() {
|
|
990
|
-
if (this._columnWidthManager.isAutoResizingUpdateQueued()) {
|
|
991
|
-
return ['table-layout:auto'].join(';');
|
|
992
|
-
}
|
|
993
|
-
return ['table-layout:fixed', getTableWidthStyle(this.widthsData)].join(
|
|
994
|
-
';'
|
|
995
|
-
);
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
get computedAriaLiveClassForNavMode() {
|
|
999
|
-
return classSet()
|
|
1000
|
-
.add({ 'slds-hide': this.state.keyboardMode !== 'NAVIGATION' })
|
|
1001
|
-
.add({
|
|
1002
|
-
'slds-assistive-text': this.state.keyboardMode === 'NAVIGATION',
|
|
1003
|
-
})
|
|
1004
|
-
.toString();
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
get computedAriaLiveClassForActionMode() {
|
|
1008
|
-
return classSet()
|
|
1009
|
-
.add({ 'slds-hide': this.state.keyboardMode !== 'ACTION' })
|
|
1010
|
-
.add({
|
|
1011
|
-
'slds-assistive-text': this.state.keyboardMode === 'ACTION',
|
|
1012
|
-
})
|
|
1013
|
-
.toString();
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
get ariaLiveNavigationModeText() {
|
|
1017
|
-
return `${i18n.ariaLiveNavigationMode}`;
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
get ariaLiveActionModeText() {
|
|
1021
|
-
return `${i18n.ariaLiveActionMode}`;
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
get ariaRowCount() {
|
|
1025
|
-
// aria-rowcount is the count of TRs in the table
|
|
1026
|
-
// It includes the # of rows of data + column header row (since this is also a TR)
|
|
1027
|
-
// In this case, a table with no rows of data still has an aria-rowcount of 1
|
|
1028
|
-
return this.state.rows.length + 1;
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
get computedTbodyStyle() {
|
|
1032
|
-
if (
|
|
1033
|
-
hasRowNumberColumn(this.state) &&
|
|
1034
|
-
getRowNumberOffset(this.state) >= 0
|
|
1035
|
-
) {
|
|
1036
|
-
return (
|
|
1037
|
-
'counter-reset: row-number ' + getRowNumberOffset(this.state)
|
|
1038
|
-
);
|
|
1113
|
+
disconnectedCallback() {
|
|
1114
|
+
if (this._privateWidthObserver) {
|
|
1115
|
+
this._privateWidthObserver.disconnect();
|
|
1039
1116
|
}
|
|
1040
|
-
return '';
|
|
1041
|
-
}
|
|
1042
1117
|
|
|
1043
|
-
|
|
1044
|
-
return !this.state.hideCheckboxColumn;
|
|
1118
|
+
this._renderManager.disconnectResizeObserver();
|
|
1045
1119
|
}
|
|
1046
1120
|
|
|
1047
|
-
|
|
1048
|
-
return !isResizeColumnDisabled(this.widthsData);
|
|
1049
|
-
}
|
|
1121
|
+
/************************** EVENT HANDLERS ***************************/
|
|
1050
1122
|
|
|
1051
1123
|
/**
|
|
1052
|
-
*
|
|
1053
|
-
*
|
|
1054
|
-
*
|
|
1055
|
-
* @
|
|
1124
|
+
* Handles the `keydown` event on <table> and the
|
|
1125
|
+
* corresponding <div> on the role-based table
|
|
1126
|
+
*
|
|
1127
|
+
* @param {KeyboardEvent} event - `keydown`
|
|
1056
1128
|
*/
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
'lightning-primitive-header-factory'
|
|
1060
|
-
);
|
|
1129
|
+
handleTableKeydown(event) {
|
|
1130
|
+
handleKeydownOnTable.call(this, event);
|
|
1061
1131
|
}
|
|
1062
1132
|
|
|
1063
1133
|
/**
|
|
1064
|
-
*
|
|
1065
|
-
*
|
|
1066
|
-
*
|
|
1134
|
+
* Handles the `keydown` event on data row <tr> (table-based) and div[role="row"] (role-based)
|
|
1135
|
+
*
|
|
1136
|
+
* @param {KeyboardEvent} event - `keydown`
|
|
1067
1137
|
*/
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
return getColumns(this.state).length;
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
get showLoadingIndicator() {
|
|
1079
|
-
return isLoading(this.state);
|
|
1080
|
-
}
|
|
1138
|
+
handleKeydownOnDataRow(event) {
|
|
1139
|
+
// we probably should not be doing this unless we actually are interested in it
|
|
1140
|
+
if (
|
|
1141
|
+
this.state.keyboardMode === 'NAVIGATION' &&
|
|
1142
|
+
this.state.rowMode === true
|
|
1143
|
+
) {
|
|
1144
|
+
event.stopPropagation();
|
|
1081
1145
|
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1146
|
+
const tr = event.currentTarget;
|
|
1147
|
+
const rowKeyValue = tr.getAttribute('data-row-key-value');
|
|
1148
|
+
const keyCode = event.keyCode;
|
|
1149
|
+
const rowHasChildren = !!tr.getAttribute('aria-expanded');
|
|
1150
|
+
const rowExpanded = tr.getAttribute('aria-expanded') === 'true';
|
|
1151
|
+
const rowLevel = tr.getAttribute('aria-level');
|
|
1086
1152
|
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1153
|
+
const evt = {
|
|
1154
|
+
target: tr,
|
|
1155
|
+
detail: {
|
|
1156
|
+
rowKeyValue,
|
|
1157
|
+
keyCode,
|
|
1158
|
+
rowHasChildren,
|
|
1159
|
+
rowExpanded,
|
|
1160
|
+
rowLevel,
|
|
1161
|
+
keyEvent: event,
|
|
1162
|
+
},
|
|
1163
|
+
};
|
|
1090
1164
|
|
|
1091
|
-
|
|
1092
|
-
styles['overflow-x'] = 'auto';
|
|
1165
|
+
reactToKeyboardOnRow(this, this.state, evt);
|
|
1093
1166
|
}
|
|
1094
|
-
|
|
1095
|
-
return Object.entries(styles)
|
|
1096
|
-
.map(([key, value]) => key + ':' + value)
|
|
1097
|
-
.join(';');
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
get showStatusBar() {
|
|
1101
|
-
return isInlineEditTriggered(this.state) && !this.suppressBottomBar;
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
get tableError() {
|
|
1105
|
-
return getTableError(this.state);
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
handleUpdateColumnSort(event) {
|
|
1109
|
-
event.stopPropagation();
|
|
1110
|
-
const { fieldName, columnKey, sortDirection } = event.detail;
|
|
1111
|
-
|
|
1112
|
-
this.fireSortedColumnChange(fieldName, columnKey, sortDirection);
|
|
1113
1167
|
}
|
|
1114
1168
|
|
|
1169
|
+
/**
|
|
1170
|
+
* Handles the `scroll` event on the table container
|
|
1171
|
+
*
|
|
1172
|
+
* @param {Event} event - `scroll`
|
|
1173
|
+
*/
|
|
1115
1174
|
handleHorizontalScroll(event) {
|
|
1116
1175
|
handleInlineEditPanelScroll.call(this, event);
|
|
1117
1176
|
}
|
|
1118
1177
|
|
|
1178
|
+
/**
|
|
1179
|
+
* Handles the `scroll` event on the child of the
|
|
1180
|
+
* table container at div.slds-scrollable_y
|
|
1181
|
+
*
|
|
1182
|
+
* @param {Event} event - `scroll`
|
|
1183
|
+
*/
|
|
1119
1184
|
handleVerticalScroll(event) {
|
|
1120
1185
|
if (this.enableInfiniteLoading) {
|
|
1121
1186
|
handleLoadMoreCheck.call(this, event);
|
|
@@ -1128,64 +1193,101 @@ export default class LightningDatatable extends LightningElement {
|
|
|
1128
1193
|
}
|
|
1129
1194
|
}
|
|
1130
1195
|
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1196
|
+
/**
|
|
1197
|
+
* Handles the `click` event on the <table> element and
|
|
1198
|
+
* the corresponding <div> in the role-based table
|
|
1199
|
+
*
|
|
1200
|
+
* @param {MouseEvent} event - `click`
|
|
1201
|
+
*/
|
|
1202
|
+
handleCellClick(event) {
|
|
1203
|
+
// handles the case when clicking on the margin/pading of the td/th
|
|
1204
|
+
const targetTagName = event.target.tagName.toLowerCase();
|
|
1135
1205
|
|
|
1136
|
-
|
|
1137
|
-
|
|
1206
|
+
if (targetTagName === 'td' || targetTagName === 'th') {
|
|
1207
|
+
// get the row/col key value from the primitive cell.
|
|
1208
|
+
const { rowKeyValue, colKeyValue } =
|
|
1209
|
+
event.target.querySelector(':first-child');
|
|
1138
1210
|
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1211
|
+
const { state, template } = this;
|
|
1212
|
+
if (
|
|
1213
|
+
state.rowMode ||
|
|
1214
|
+
!isActiveCell(state, rowKeyValue, colKeyValue)
|
|
1215
|
+
) {
|
|
1216
|
+
if (state.rowMode && state.activeCell) {
|
|
1217
|
+
unsetRowNavigationMode(state);
|
|
1218
|
+
const { rowIndex } = getIndexesActiveCell(state);
|
|
1219
|
+
updateTabIndexRow(state, rowIndex, -1);
|
|
1220
|
+
}
|
|
1221
|
+
this.setActiveCell(rowKeyValue, colKeyValue);
|
|
1222
|
+
}
|
|
1145
1223
|
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
columnWidths: getCustomerColumnWidths(state, widthsData),
|
|
1151
|
-
isUserTriggered: !!isUserTriggered,
|
|
1152
|
-
},
|
|
1153
|
-
});
|
|
1154
|
-
this.dispatchEvent(event);
|
|
1224
|
+
if (!datatableHasFocus(state, template)) {
|
|
1225
|
+
setCellClickedForFocus(state);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1155
1228
|
}
|
|
1156
1229
|
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1230
|
+
/**
|
|
1231
|
+
* Handles the `privateupdatecolsort` event on lightning-datatable
|
|
1232
|
+
*
|
|
1233
|
+
* @param {CustomEvent} event - `privateupdatecolsort`
|
|
1234
|
+
*/
|
|
1235
|
+
handleUpdateColumnSort(event) {
|
|
1236
|
+
event.stopPropagation();
|
|
1237
|
+
const { fieldName, columnKey, sortDirection } = event.detail;
|
|
1165
1238
|
|
|
1166
|
-
|
|
1167
|
-
requestAnimationFrame(() => {
|
|
1168
|
-
thead.style.display = '';
|
|
1169
|
-
});
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1239
|
+
this.fireSortedColumnChange(fieldName, columnKey, sortDirection);
|
|
1172
1240
|
}
|
|
1173
1241
|
|
|
1242
|
+
/**
|
|
1243
|
+
* Handles the `resizecol` event on lightning-datatable
|
|
1244
|
+
*
|
|
1245
|
+
* @param {CustomEvent} event - `resizecol`
|
|
1246
|
+
*/
|
|
1174
1247
|
handleResizeColumn(event) {
|
|
1175
1248
|
event.stopPropagation();
|
|
1176
1249
|
const { state, widthsData } = this;
|
|
1177
1250
|
const { colIndex, widthDelta } = event.detail;
|
|
1178
1251
|
if (widthDelta !== 0) {
|
|
1179
|
-
resizeColumnWithDelta(
|
|
1252
|
+
resizeColumnWithDelta(
|
|
1253
|
+
getColumns(state),
|
|
1254
|
+
widthsData,
|
|
1255
|
+
colIndex,
|
|
1256
|
+
widthDelta
|
|
1257
|
+
);
|
|
1180
1258
|
this.fireOnResize(true);
|
|
1181
1259
|
this.safariHeaderFix();
|
|
1182
1260
|
}
|
|
1183
1261
|
}
|
|
1184
1262
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1263
|
+
/**
|
|
1264
|
+
* Handles the `privateresizestart` event on the <tr> and the corresponding
|
|
1265
|
+
* <div> in the role-based table on the column header row
|
|
1266
|
+
*
|
|
1267
|
+
* @param {CustomEvent} event - `privateresizestart`
|
|
1268
|
+
*/
|
|
1269
|
+
handleResizeStart(event) {
|
|
1270
|
+
event.stopPropagation();
|
|
1271
|
+
this._isResizing = true;
|
|
1187
1272
|
}
|
|
1188
1273
|
|
|
1274
|
+
/**
|
|
1275
|
+
* Handles the `privateresizeend` event on the <tr> and the corresponding
|
|
1276
|
+
* <div> in the role-based table on the column header row
|
|
1277
|
+
*
|
|
1278
|
+
* @param {CustomEvent} event - `privateresizeend`
|
|
1279
|
+
*/
|
|
1280
|
+
handleResizeEnd(event) {
|
|
1281
|
+
event.stopPropagation();
|
|
1282
|
+
this._isResizing = false;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
/**
|
|
1286
|
+
* Handles the `selectallrows`, `deselectallrows`, `selectrow`, `deselectrow`
|
|
1287
|
+
* events on lightning-datatable
|
|
1288
|
+
*
|
|
1289
|
+
* @param {CustomEvent} event - `selectallrows`, `deselectallrows`, `selectrow`, `deselectrow`
|
|
1290
|
+
*/
|
|
1189
1291
|
handleSelectionCellClick(event) {
|
|
1190
1292
|
this.handleCellFocusByClick(event);
|
|
1191
1293
|
|
|
@@ -1200,6 +1302,11 @@ export default class LightningDatatable extends LightningElement {
|
|
|
1200
1302
|
}
|
|
1201
1303
|
}
|
|
1202
1304
|
|
|
1305
|
+
/**
|
|
1306
|
+
* Handles the `privatecellfocusedbyclick` event on lightning-datatable
|
|
1307
|
+
*
|
|
1308
|
+
* @param {CustomEvent} event - `privatecellfocusedbyclick`
|
|
1309
|
+
*/
|
|
1203
1310
|
handleCellFocusByClick(event) {
|
|
1204
1311
|
event.stopPropagation();
|
|
1205
1312
|
const { rowKeyValue, colKeyValue, needsRefocusOnCellElement } =
|
|
@@ -1216,47 +1323,11 @@ export default class LightningDatatable extends LightningElement {
|
|
|
1216
1323
|
}
|
|
1217
1324
|
}
|
|
1218
1325
|
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
// get the row/col key value from the primitive cell.
|
|
1225
|
-
const { rowKeyValue, colKeyValue } =
|
|
1226
|
-
event.target.querySelector(':first-child');
|
|
1227
|
-
|
|
1228
|
-
const { state, template } = this;
|
|
1229
|
-
if (
|
|
1230
|
-
state.rowMode ||
|
|
1231
|
-
!isActiveCell(state, rowKeyValue, colKeyValue)
|
|
1232
|
-
) {
|
|
1233
|
-
if (state.rowMode && state.activeCell) {
|
|
1234
|
-
unsetRowNavigationMode(state);
|
|
1235
|
-
const { rowIndex } = getIndexesActiveCell(state);
|
|
1236
|
-
updateTabIndexRow(state, rowIndex, -1);
|
|
1237
|
-
}
|
|
1238
|
-
this.setActiveCell(rowKeyValue, colKeyValue);
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
if (!datatableHasFocus(state, template)) {
|
|
1242
|
-
setCellClickedForFocus(state);
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
setActiveCell(rowKeyValue, colKeyValue) {
|
|
1248
|
-
const { template, state } = this;
|
|
1249
|
-
const { rowIndex, colIndex } = getIndexesByKeys(
|
|
1250
|
-
state,
|
|
1251
|
-
rowKeyValue,
|
|
1252
|
-
colKeyValue
|
|
1253
|
-
);
|
|
1254
|
-
setBlurActiveCell(template, state);
|
|
1255
|
-
updateActiveCell(state, rowKeyValue, colKeyValue);
|
|
1256
|
-
addFocusStylesToActiveCell(template, state);
|
|
1257
|
-
updateTabIndex(state, rowIndex, colIndex, 0);
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1326
|
+
/**
|
|
1327
|
+
* Handles the `privatecellfalseblurred` event on lightning-datatable
|
|
1328
|
+
*
|
|
1329
|
+
* @param {CustomEvent} event - `privatecellfalseblurred`
|
|
1330
|
+
*/
|
|
1260
1331
|
handleFalseCellBlur(event) {
|
|
1261
1332
|
event.stopPropagation();
|
|
1262
1333
|
const { template, state } = this;
|
|
@@ -1268,71 +1339,52 @@ export default class LightningDatatable extends LightningElement {
|
|
|
1268
1339
|
}
|
|
1269
1340
|
|
|
1270
1341
|
/**
|
|
1271
|
-
*
|
|
1272
|
-
*
|
|
1273
|
-
*/
|
|
1274
|
-
@api
|
|
1275
|
-
getSelectedRows() {
|
|
1276
|
-
const data = unwrap(getData(this.state));
|
|
1277
|
-
return this.state.rows.reduce((prev, row, index) => {
|
|
1278
|
-
if (row.isSelected) {
|
|
1279
|
-
prev.push(data[index]);
|
|
1280
|
-
}
|
|
1281
|
-
return prev;
|
|
1282
|
-
}, []);
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
/**
|
|
1286
|
-
* Opens the inline edit panel for the datatable's currently active cell. If the active cell is not
|
|
1287
|
-
* editable, then the panel is instead opened for the first editable cell in the table. Given two
|
|
1288
|
-
* distinct cells, C_x and C_y, C_x is considered "first" in the cell ordering if the following condition
|
|
1289
|
-
* evaluates to true:
|
|
1342
|
+
* Handles the `focusin` event on <table> and the corresponding
|
|
1343
|
+
* <div> on the role-based table
|
|
1290
1344
|
*
|
|
1291
|
-
*
|
|
1292
|
-
*
|
|
1293
|
-
* If there is no data in the table or there are no editable cells in the table then calling this function
|
|
1294
|
-
* results in a no-op.
|
|
1345
|
+
* @param {FocusEvent} event - `focusin`
|
|
1295
1346
|
*/
|
|
1296
|
-
@api
|
|
1297
|
-
openInlineEdit() {
|
|
1298
|
-
openInlineEditOnActiveCell(this);
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
1347
|
handleTableFocusIn(event) {
|
|
1302
1348
|
handleDatatableFocusIn.call(this, event);
|
|
1303
1349
|
}
|
|
1304
1350
|
|
|
1351
|
+
/**
|
|
1352
|
+
* Handles the `focusout` event on <table> and the corresponding
|
|
1353
|
+
* <div> on the role-based table
|
|
1354
|
+
*
|
|
1355
|
+
* @param {FocusEvent} event - `focusout`
|
|
1356
|
+
*/
|
|
1305
1357
|
handleTableFocusOut(event) {
|
|
1306
|
-
|
|
1358
|
+
handleDatatableFocusOut.call(this, event);
|
|
1307
1359
|
}
|
|
1308
1360
|
|
|
1309
1361
|
/**
|
|
1310
|
-
*
|
|
1362
|
+
* Handles the `ieditfinished` event on the inline edit panel -
|
|
1363
|
+
* `lightning-primitive-datatable-iedit-panel`
|
|
1364
|
+
*
|
|
1365
|
+
* @param {CustomEvent} event - `ieditfinished`
|
|
1311
1366
|
*/
|
|
1312
|
-
getViewableRect() {
|
|
1313
|
-
const scrollerX = this.template
|
|
1314
|
-
.querySelector('.slds-scrollable_x')
|
|
1315
|
-
.getBoundingClientRect();
|
|
1316
|
-
const scrollerY = this.template
|
|
1317
|
-
.querySelector('.slds-scrollable_y')
|
|
1318
|
-
.getBoundingClientRect();
|
|
1319
|
-
|
|
1320
|
-
return {
|
|
1321
|
-
left: scrollerX.left,
|
|
1322
|
-
right: scrollerX.right,
|
|
1323
|
-
top: scrollerY.top,
|
|
1324
|
-
bottom: scrollerY.bottom,
|
|
1325
|
-
};
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
1367
|
handleInlineEditFinish(event) {
|
|
1329
1368
|
handleInlineEditFinish.call(this, event);
|
|
1330
1369
|
}
|
|
1331
1370
|
|
|
1371
|
+
/**
|
|
1372
|
+
* Handles the `masscheckboxchange` event on the inline edit panel -
|
|
1373
|
+
* `lightning-primitive-datatable-iedit-panel`
|
|
1374
|
+
*
|
|
1375
|
+
* @param {CustomEvent} event - `masscheckboxchange`
|
|
1376
|
+
*/
|
|
1332
1377
|
handleMassCheckboxChange(event) {
|
|
1333
1378
|
handleMassCheckboxChange.call(this, event);
|
|
1334
1379
|
}
|
|
1335
1380
|
|
|
1381
|
+
/**
|
|
1382
|
+
* Handles the `privatesave` event on the status bar -
|
|
1383
|
+
* `lightning-primitive-datatable-status-bar` and
|
|
1384
|
+
* fires the `save` custom event
|
|
1385
|
+
*
|
|
1386
|
+
* @param {CustomEvent} event - `privatesave`
|
|
1387
|
+
*/
|
|
1336
1388
|
handleInlineEditSave(event) {
|
|
1337
1389
|
event.stopPropagation();
|
|
1338
1390
|
event.preventDefault();
|
|
@@ -1349,6 +1401,13 @@ export default class LightningDatatable extends LightningElement {
|
|
|
1349
1401
|
);
|
|
1350
1402
|
}
|
|
1351
1403
|
|
|
1404
|
+
/**
|
|
1405
|
+
* Handles the `privatecancel` event on the status bar -
|
|
1406
|
+
* `lightning-primitive-datatable-status-bar` and
|
|
1407
|
+
* fires the `cancel` custom event
|
|
1408
|
+
*
|
|
1409
|
+
* @param {CustomEvent} event - `privatecancel`
|
|
1410
|
+
*/
|
|
1352
1411
|
handleInlineEditCancel(event) {
|
|
1353
1412
|
event.stopPropagation();
|
|
1354
1413
|
event.preventDefault();
|
|
@@ -1365,17 +1424,163 @@ export default class LightningDatatable extends LightningElement {
|
|
|
1365
1424
|
}
|
|
1366
1425
|
}
|
|
1367
1426
|
|
|
1368
|
-
|
|
1369
|
-
|
|
1427
|
+
/************************ EVENT DISPATCHERS **************************/
|
|
1428
|
+
|
|
1429
|
+
fireSelectedRowsChange(selectedRows) {
|
|
1430
|
+
const event = new CustomEvent('rowselection', {
|
|
1431
|
+
detail: { selectedRows },
|
|
1432
|
+
});
|
|
1433
|
+
|
|
1434
|
+
this.dispatchEvent(event);
|
|
1370
1435
|
}
|
|
1371
1436
|
|
|
1372
|
-
|
|
1373
|
-
event
|
|
1374
|
-
|
|
1437
|
+
fireSortedColumnChange(fieldName, columnKey, sortDirection) {
|
|
1438
|
+
const event = new CustomEvent('sort', {
|
|
1439
|
+
detail: { fieldName, columnKey, sortDirection },
|
|
1440
|
+
});
|
|
1441
|
+
this.dispatchEvent(event);
|
|
1375
1442
|
}
|
|
1376
1443
|
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1444
|
+
fireOnResize(isUserTriggered) {
|
|
1445
|
+
const { state, widthsData } = this;
|
|
1446
|
+
const event = new CustomEvent('resize', {
|
|
1447
|
+
detail: {
|
|
1448
|
+
columnWidths: getCustomerColumnWidths(
|
|
1449
|
+
getColumns(state),
|
|
1450
|
+
widthsData
|
|
1451
|
+
),
|
|
1452
|
+
isUserTriggered: !!isUserTriggered,
|
|
1453
|
+
},
|
|
1454
|
+
});
|
|
1455
|
+
this.dispatchEvent(event);
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
/************************* HELPER FUNCTIONS **************************/
|
|
1459
|
+
|
|
1460
|
+
updateRowsState() {
|
|
1461
|
+
const { state, widthsData, template } = this;
|
|
1462
|
+
// calculate cell to focus next before indexes are updated
|
|
1463
|
+
setCellToFocusFromPrev(state, template);
|
|
1464
|
+
|
|
1465
|
+
this.updateRowsAndCellIndexes(state);
|
|
1466
|
+
|
|
1467
|
+
if (this.viewportRendering) {
|
|
1468
|
+
this._renderManager.updateViewportRendering(this);
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
this._columnWidthManager.handleRowNumberOffsetChange(state, widthsData);
|
|
1472
|
+
// update celltofocus next to null if the row still exists after indexes calculation
|
|
1473
|
+
updateCellToFocusFromPrev(state);
|
|
1474
|
+
syncSelectedRowsKeys(state, this.getSelectedRows()).ifChanged(() => {
|
|
1475
|
+
// Only trigger row selection event once after all the setters have executed
|
|
1476
|
+
// Otherwise, event can be fired with stale data if not all setters have been triggered
|
|
1477
|
+
if (!this._rowSelectionEventPending) {
|
|
1478
|
+
this._rowSelectionEventPending = true;
|
|
1479
|
+
Promise.resolve().then(() => {
|
|
1480
|
+
if (this._rowSelectionEventPending) {
|
|
1481
|
+
this.fireSelectedRowsChange(this.getSelectedRows());
|
|
1482
|
+
this._rowSelectionEventPending = false;
|
|
1483
|
+
}
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
});
|
|
1487
|
+
syncActiveCell(state);
|
|
1488
|
+
|
|
1489
|
+
if (state.keyboardMode === 'NAVIGATION') {
|
|
1490
|
+
updateTabIndexActiveCell(state);
|
|
1491
|
+
updateTabIndexActiveRow(state);
|
|
1492
|
+
}
|
|
1493
|
+
// if there is previously focused cell which was deleted set focus from celltofocus next
|
|
1494
|
+
if (state.cellToFocusNext && state.activeCell) {
|
|
1495
|
+
setFocusActiveCell(this.template, this.state);
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
updateColumns(columns) {
|
|
1500
|
+
const { state, widthsData, template } = this;
|
|
1501
|
+
const hadTreeDataTypePreviously = hasTreeDataType(state);
|
|
1502
|
+
// calculate cell to focus next before indexes are updated
|
|
1503
|
+
setCellToFocusFromPrev(state, template);
|
|
1504
|
+
normalizeColumns(state, columns, this.privateTypes);
|
|
1505
|
+
setDirtyValues(state, this._draftValues);
|
|
1506
|
+
updateRowNavigationMode(hadTreeDataTypePreviously, state);
|
|
1507
|
+
state.headerIndexes = generateHeaderIndexes(getColumns(state));
|
|
1508
|
+
// Updates state.wrapText and when isWrapableType, sets internal header actions
|
|
1509
|
+
updateHeaderActions(state);
|
|
1510
|
+
this.updateRowsAndCellIndexes(state);
|
|
1511
|
+
updateSelectionState(state);
|
|
1512
|
+
this._columnWidthManager.handleRowNumberOffsetChange(state, widthsData);
|
|
1513
|
+
updateColumnWidthsMetadata(getColumns(state), widthsData);
|
|
1514
|
+
// set the celltofocus next to null if the column still exists after indexes calculation
|
|
1515
|
+
updateCellToFocusFromPrev(state);
|
|
1516
|
+
|
|
1517
|
+
if (getColumns(state).length !== getColumnsWidths(widthsData).length) {
|
|
1518
|
+
if (getData(state).length > 0) {
|
|
1519
|
+
// when there are column changes, update the active cell
|
|
1520
|
+
syncActiveCell(state);
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
if (state.keyboardMode === 'NAVIGATION') {
|
|
1524
|
+
updateTabIndexActiveCell(state);
|
|
1525
|
+
updateTabIndexActiveRow(state);
|
|
1526
|
+
}
|
|
1527
|
+
// if there is previously focused cell which was deleted set focus from celltofocus next
|
|
1528
|
+
if (state.cellToFocusNext && state.activeCell) {
|
|
1529
|
+
setFocusActiveCell(this.template, this.state);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
setSelectedRows(value) {
|
|
1534
|
+
setSelectedRowsKeys(this.state, value);
|
|
1535
|
+
handleRowSelectionChange.call(this);
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
setActiveCell(rowKeyValue, colKeyValue) {
|
|
1539
|
+
const { template, state } = this;
|
|
1540
|
+
const { rowIndex, colIndex } = getIndexesByKeys(
|
|
1541
|
+
state,
|
|
1542
|
+
rowKeyValue,
|
|
1543
|
+
colKeyValue
|
|
1544
|
+
);
|
|
1545
|
+
setBlurActiveCell(template, state);
|
|
1546
|
+
updateActiveCell(state, rowKeyValue, colKeyValue);
|
|
1547
|
+
addFocusStylesToActiveCell(template, state);
|
|
1548
|
+
updateTabIndex(state, rowIndex, colIndex, 0);
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
/**
|
|
1552
|
+
* @return {Object} containing the visible dimensions of the table { left, right, top, bottom, }
|
|
1553
|
+
*/
|
|
1554
|
+
getViewableRect() {
|
|
1555
|
+
const scrollerX = this.template
|
|
1556
|
+
.querySelector('.slds-scrollable_x')
|
|
1557
|
+
.getBoundingClientRect();
|
|
1558
|
+
const scrollerY = this.template
|
|
1559
|
+
.querySelector('.slds-scrollable_y')
|
|
1560
|
+
.getBoundingClientRect();
|
|
1561
|
+
|
|
1562
|
+
return {
|
|
1563
|
+
left: scrollerX.left,
|
|
1564
|
+
right: scrollerX.right,
|
|
1565
|
+
top: scrollerY.top,
|
|
1566
|
+
bottom: scrollerY.bottom,
|
|
1567
|
+
};
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
// W-6363867, W-7143375 Safari Refresh Bug
|
|
1571
|
+
safariHeaderFix() {
|
|
1572
|
+
if (isSafari) {
|
|
1573
|
+
const thead = this.template.querySelector('thead');
|
|
1574
|
+
|
|
1575
|
+
if (thead) {
|
|
1576
|
+
/* Safari hack: hide and show the table head to force a browser repaint */
|
|
1577
|
+
thead.style.display = 'none';
|
|
1578
|
+
|
|
1579
|
+
// eslint-disable-next-line @lwc/lwc/no-async-operation
|
|
1580
|
+
requestAnimationFrame(() => {
|
|
1581
|
+
thead.style.display = '';
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1380
1585
|
}
|
|
1381
1586
|
}
|