lightning-base-components 1.14.3-alpha → 1.15.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 +37 -4
- package/package.json +11 -4
- package/scopedImports/@salesforce-internal-core.appVersion.js +1 -1
- package/scopedImports/@salesforce-label-LightningModalBase.cancelandclose.js +1 -0
- package/scopedImports/@salesforce-label-LightningProgressBar.progressBar.js +1 -0
- package/src/lightning/alert/__docs__/alert.md +101 -0
- package/src/lightning/alert/__examples__disabled/basic/basic.css +7 -0
- package/src/lightning/alert/__examples__disabled/basic/basic.html +8 -0
- package/src/lightning/alert/__examples__disabled/basic/basic.js +14 -0
- package/src/lightning/alert/alert.html +3 -0
- package/src/lightning/alert/alert.js +78 -0
- package/src/lightning/alert/alert.js-meta.xml +6 -0
- package/src/lightning/ariaObserver/__component__/ariaObserver.spec.js +9 -0
- package/src/lightning/ariaObserver/ariaObserver.js +24 -35
- package/src/lightning/baseFormattedText/baseFormattedText.html +6 -1
- package/src/lightning/baseFormattedText/baseFormattedText.js +5 -0
- package/src/lightning/button/__wdio__/utam/utam.html +3 -0
- package/src/lightning/button/__wdio__/utam/utam.js +3 -0
- package/src/lightning/button/__wdio__/utam/utam.spec.js +20 -0
- package/src/lightning/buttonMenu/buttonMenu.js +12 -0
- package/src/lightning/confirm/__docs__/confirm.md +100 -0
- package/src/lightning/confirm/__examples__disabled/basic/basic.css +7 -0
- package/src/lightning/confirm/__examples__disabled/basic/basic.html +8 -0
- package/src/lightning/confirm/__examples__disabled/basic/basic.js +14 -0
- package/src/lightning/confirm/confirm.html +3 -0
- package/src/lightning/confirm/confirm.js +80 -0
- package/src/lightning/confirm/confirm.js-meta.xml +6 -0
- package/src/lightning/datatable/__examples__/withInfiniteLoading/fetchDataHelper.js +21 -0
- package/src/lightning/datatable/__examples__/withInfiniteLoading/withInfiniteLoading.html +13 -0
- package/src/lightning/datatable/__examples__/withInfiniteLoading/withInfiniteLoading.js +42 -0
- package/src/lightning/datatable/__wdio__/utam/utam.html +17 -0
- package/src/lightning/datatable/__wdio__/utam/utam.js +91 -0
- package/src/lightning/datatable/__wdio__/utam/utam.spec.js +189 -0
- package/src/lightning/datatable/autoWidthStrategy.js +170 -61
- package/src/lightning/datatable/{resizer.js → columnResizer.js} +0 -0
- package/src/lightning/datatable/columnWidthManager.js +226 -44
- package/src/lightning/datatable/columns.js +166 -71
- package/src/lightning/datatable/datatable.js +136 -60
- package/src/lightning/datatable/fixedWidthStrategy.js +43 -8
- package/src/lightning/datatable/headerActions.js +2 -2
- package/src/lightning/datatable/infiniteLoading.js +100 -28
- package/src/lightning/datatable/inlineEdit.js +21 -30
- package/src/lightning/datatable/keyboard.js +166 -131
- package/src/lightning/datatable/renderManager.js +117 -122
- package/src/lightning/datatable/{datatableResizeObserver.js → resizeObserver.js} +46 -29
- package/src/lightning/datatable/resizeSensor.js +19 -3
- package/src/lightning/datatable/rowSelection.js +1 -1
- package/src/lightning/datatable/rowSelectionShared.js +33 -20
- package/src/lightning/datatable/rows.js +9 -8
- package/src/lightning/datatable/sort.js +8 -8
- package/src/lightning/datatable/state.js +14 -2
- package/src/lightning/datatable/templates/div/div.html +133 -119
- package/src/lightning/datatable/templates/table/table.html +10 -2
- package/src/lightning/datatable/tree.js +25 -0
- package/src/lightning/datatable/types.js +77 -9
- package/src/lightning/datatable/utils.js +51 -24
- package/src/lightning/datatable/virtualization.js +319 -0
- package/src/lightning/datatable/widthManagerShared.js +27 -3
- package/src/lightning/datatable/wrapText.js +115 -48
- package/src/lightning/datepicker/__perf__DISABLED/datepickerWithCalendarOpen.perf.js +55 -0
- package/src/lightning/formattedDateTime/__docs__/formattedDateTime.md +36 -3
- package/src/lightning/formattedDateTime/__examples__/datetime/datetime.html +2 -2
- package/src/lightning/formattedDateTime/__examples__/datetime/datetime.js +3 -1
- package/src/lightning/formattedDateTime/__examples__/time/time.html +1 -1
- package/src/lightning/formattedDateTime/__examples__/time/time.js +3 -1
- package/src/lightning/formattedDateTime/formattedDateTime.js +1 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplates/buildTemplates/templates.js +8 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplates/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/templates.js +8 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesRtl/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesStandard/buildTemplates/templates.js +4 -1
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/dashboard_component.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/standard/travel_mode.html +2 -2
- package/src/lightning/iconSvgTemplatesStandardRtl/buildTemplates/templates.js +4 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/templates.js +5 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesUtility/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/templates.js +5 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/data_model.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product.html +1 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/serialized_product_transaction.html +2 -1
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/slack.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/tableau.html +7 -0
- package/src/lightning/iconSvgTemplatesUtilityRtl/buildTemplates/utility/video_off.html +7 -0
- package/src/lightning/input/__docs__/input.md +2 -0
- package/src/lightning/input/input.html +2 -5
- package/src/lightning/interactiveDialogBase/interactiveDialogBase.css +494 -0
- package/src/lightning/interactiveDialogBase/interactiveDialogBase.html +63 -0
- package/src/lightning/interactiveDialogBase/interactiveDialogBase.js +200 -0
- package/src/lightning/menuItem/menuItem.js +4 -1
- package/src/lightning/modalBase/modalBase.css +20 -0
- package/src/lightning/modalBase/modalBase.html +54 -0
- package/src/lightning/modalBase/modalBase.js +1039 -0
- package/src/lightning/overlay/__docs__/overlay.md +90 -0
- package/src/lightning/overlay/__examples__/alert/alert.html +27 -0
- package/src/lightning/overlay/__examples__/alert/alert.js +33 -0
- package/src/lightning/overlay/__examples__/basic/basic.css +7 -0
- package/src/lightning/overlay/__examples__/basic/basic.html +18 -0
- package/src/lightning/overlay/__examples__/basic/basic.js +61 -0
- package/src/lightning/overlay/__examples__/demo/demo.html +29 -0
- package/src/lightning/overlay/__examples__/demo/demo.js +40 -0
- package/src/lightning/overlay/__examples__/panel/panel.html +17 -0
- package/src/lightning/overlay/__examples__/panel/panel.js +21 -0
- package/src/lightning/overlay/overlay.html +3 -0
- package/src/lightning/overlay/overlay.js +45 -0
- package/src/lightning/overlayContainer/__docs__/overlayContainer.md +0 -0
- package/src/lightning/overlayContainer/overlayContainer.html +3 -0
- package/src/lightning/overlayContainer/overlayContainer.js +138 -0
- package/src/lightning/overlayManager/overlayManager.js +54 -0
- package/src/lightning/overlayUtils/overlayUtils.js +17 -0
- package/src/lightning/progressBar/progressBar.html +2 -1
- package/src/lightning/progressBar/progressBar.js +18 -1
- package/src/lightning/prompt/__docs__/prompt.md +102 -0
- package/src/lightning/prompt/__examples__disabled/basic/basic.css +7 -0
- package/src/lightning/prompt/__examples__disabled/basic/basic.html +8 -0
- package/src/lightning/prompt/__examples__disabled/basic/basic.js +15 -0
- package/src/lightning/prompt/prompt.css +81 -0
- package/src/lightning/prompt/prompt.html +8 -0
- package/src/lightning/prompt/prompt.js +92 -0
- package/src/lightning/prompt/prompt.js-meta.xml +6 -0
- package/src/lightning/spinner/spinner.html +1 -1
- package/src/lightning/spinner/spinner.js +12 -0
- package/src/lightning/utilsPrivate/phonify.js +1 -1
- package/scopedImports/@salesforce-label-LightningModalBase.close.js +0 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
The `lightning/confirm` module lets you create a confirm modal within your component. Use `LightningConfirm` on your component to ask the user to respond before they continue.
|
|
2
|
+
|
|
3
|
+
`lightning/confirm` is not supported on mobile devices.
|
|
4
|
+
|
|
5
|
+
Use `LightningConfirm.open()` instead of the native `window.confirm()` for a more consistent user experience. They have similar functions, but `LightningConfirm.open()` works in cross-origin iframes, where the `.confirm()` method is no longer supported in Chrome and Safari. Unlike `window.confirm()`, `LightningConfirm.open()` doesn't halt execution on the page, it returns a Promise. Use `async`/`await` or `.then()` for any code you want to execute after the confirm has closed.
|
|
6
|
+
|
|
7
|
+
Import `LightningConfirm` from the `lightning/confirm` module in the component that will launch the confirm modal, and call `LightningConfirm.open()` with your desired attributes.
|
|
8
|
+
|
|
9
|
+
This example creates a headerless confirm modal with two buttons, **OK** and **Cancel**. The `.open()` function returns a promise that resolves to true when you click **OK** and false when you click **Cancel**.
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<!-- c/myApp.html -->
|
|
13
|
+
<template>
|
|
14
|
+
<lightning-button onclick="{handleConfirmClick}" label="Open Confirm Modal">
|
|
15
|
+
</lightning-button>
|
|
16
|
+
</template>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
import { LightningElement } from 'lwc';
|
|
21
|
+
import LightningConfirm from 'lightning/confirm';
|
|
22
|
+
|
|
23
|
+
export default class MyApp extends LightningElement {
|
|
24
|
+
async handleConfirmClick() {
|
|
25
|
+
const result = await LightningConfirm.open({
|
|
26
|
+
message: 'this is the prompt message',
|
|
27
|
+
variant: 'headerless',
|
|
28
|
+
label: 'this is the aria-label value',
|
|
29
|
+
// setting theme would have no effect
|
|
30
|
+
});
|
|
31
|
+
//Confirm has been closed
|
|
32
|
+
//result is true if OK was clicked
|
|
33
|
+
//and false if cancel was clicked
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Component Styling
|
|
39
|
+
|
|
40
|
+
This component uses the Salesforce Lightning Design System (SLDS) [`prompt` blueprint](https://www.lightningdesignsystem.com/components/prompt/#site-main-content).
|
|
41
|
+
|
|
42
|
+
`LightningConfirm` supports the following attributes:
|
|
43
|
+
|
|
44
|
+
- `message`: Message text that displays in the confirm.
|
|
45
|
+
- `label`: Header text, also used as the `aria-label`. Default string is `Confirm`.
|
|
46
|
+
- `variant`: Two values, `header` and `headerless`. Default value is `header`.
|
|
47
|
+
- `theme`: Color theme for the header. The `theme` attribute supports the following [options](https://www.lightningdesignsystem.com/utilities/themes/#site-main-content) from SLDS:
|
|
48
|
+
- `default`: white
|
|
49
|
+
- `shade`: gray
|
|
50
|
+
- `inverse`: dark blue
|
|
51
|
+
- `alt-inverse`: darker blue
|
|
52
|
+
- `success`: green
|
|
53
|
+
- `info`: gray-ish blue
|
|
54
|
+
- `warning`: yellow
|
|
55
|
+
- `error`: red
|
|
56
|
+
- `offline`: black
|
|
57
|
+
|
|
58
|
+
If an invalid value is provided, `LightningConfirm` uses the `default` theme.
|
|
59
|
+
|
|
60
|
+
#### Testing Your Component's Confirm
|
|
61
|
+
|
|
62
|
+
Code using `LightningConfirm` can be tested by mocking the `LightningConfirm.open()` method.
|
|
63
|
+
|
|
64
|
+
The example below uses a button to open a confirm dialog and sets the result in a template.
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<button data-button onclick="{handleClick}">Open Confirm</button>
|
|
68
|
+
<div data-result>{result}</div>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
import LightningConfirm from 'lightning/confirm';
|
|
73
|
+
jest.mock('lightning/confirm');
|
|
74
|
+
|
|
75
|
+
test(() => {
|
|
76
|
+
// Create and appendChild(element)
|
|
77
|
+
|
|
78
|
+
const buttonEle = element.shadowRoot.querySelector('[data-button]');
|
|
79
|
+
const resultEle = element.shadowRoot.querySelector('[data-result]');
|
|
80
|
+
|
|
81
|
+
// Mock .open()
|
|
82
|
+
// Pass true if testing when user clicks "OK"
|
|
83
|
+
// Pass false if testing when user clicks "Cancel"
|
|
84
|
+
LightningConfirm.open = jest.fn().mockResolvedValue(true);
|
|
85
|
+
// Initial value
|
|
86
|
+
expect(resultEle.textContent).toBe('unknown');
|
|
87
|
+
// Click modal open button
|
|
88
|
+
buttonEle.click();
|
|
89
|
+
|
|
90
|
+
// Click handler render cycle
|
|
91
|
+
await Promise.resolve();
|
|
92
|
+
// Render cycle triggered by tracked value {result}
|
|
93
|
+
await Promise.resolve();
|
|
94
|
+
|
|
95
|
+
// Verify result is set in the template
|
|
96
|
+
expect(resultEle.textContent).toBe('true');
|
|
97
|
+
// Open triggered once
|
|
98
|
+
expect(LightningConfirm.open.mock.calls).toHaveLength(1);
|
|
99
|
+
})
|
|
100
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LightningElement } from 'lwc';
|
|
2
|
+
import LightningConfirm from 'lightning/confirm';
|
|
3
|
+
|
|
4
|
+
export default class ConfirmBasic extends LightningElement {
|
|
5
|
+
handleConfirmModal() {
|
|
6
|
+
LightningConfirm.open({
|
|
7
|
+
message: 'this is the confirm message',
|
|
8
|
+
label: 'Please Confirm',
|
|
9
|
+
theme: 'warning',
|
|
10
|
+
}).then((result) => {
|
|
11
|
+
console.log('confirm result', result);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { api } from 'lwc';
|
|
2
|
+
import LightningInteractiveDialogBase from 'lightning/interactiveDialogBase';
|
|
3
|
+
import { parent, instanceName, secure } from 'lightning/overlayUtils';
|
|
4
|
+
import LightningOverlay from 'lightning/overlay';
|
|
5
|
+
import labelDefault from '@salesforce/label/LightningConfirm.defaultLabel';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Create a confirm modal within your component that asks the user
|
|
9
|
+
* to respond before they continue.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export default class LightningConfirm extends LightningOverlay {
|
|
13
|
+
static [instanceName] = 'lightning-confirm';
|
|
14
|
+
static [parent] = LightningInteractiveDialogBase;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* value to use for header text in "header" variant
|
|
18
|
+
* or aria-label in "headerless" variant
|
|
19
|
+
* @type {string}
|
|
20
|
+
* @default "Confirm" (translated accordingly)
|
|
21
|
+
*/
|
|
22
|
+
@api label = labelDefault;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* text to display in body of modal
|
|
26
|
+
*/
|
|
27
|
+
@api message = '';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* variant to use for alert; may be
|
|
31
|
+
* set to "header" or "headerless"
|
|
32
|
+
*/
|
|
33
|
+
@api variant = 'header';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* theme to use when variant is "header"
|
|
37
|
+
* valid values are based on SLDS themes and are
|
|
38
|
+
* listed in "themeOptions" of interactiveDialogBase.js
|
|
39
|
+
*/
|
|
40
|
+
@api theme = 'default';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Dispatches privateclose event
|
|
44
|
+
* and closes dialog
|
|
45
|
+
*/
|
|
46
|
+
close(result) {
|
|
47
|
+
const promise = new Promise((resolve) => {
|
|
48
|
+
this.dispatchEvent(
|
|
49
|
+
new CustomEvent('privateclose', {
|
|
50
|
+
detail: {
|
|
51
|
+
resolve,
|
|
52
|
+
[secure]: true,
|
|
53
|
+
},
|
|
54
|
+
bubbles: true,
|
|
55
|
+
})
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
super.close(result, promise);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Dispatches privatechildrender event
|
|
63
|
+
* with data parent needs to correctly render
|
|
64
|
+
*/
|
|
65
|
+
renderedCallback() {
|
|
66
|
+
const evt = new CustomEvent('privatechildrender', {
|
|
67
|
+
bubbles: true,
|
|
68
|
+
detail: {
|
|
69
|
+
message: this.message,
|
|
70
|
+
label: this.label,
|
|
71
|
+
hideCancel: false,
|
|
72
|
+
showDescription: true,
|
|
73
|
+
getOkValue: () => true,
|
|
74
|
+
getCancelValue: () => false,
|
|
75
|
+
role: 'alertdialog',
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
this.dispatchEvent(evt);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const recordMetadata = {
|
|
2
|
+
name: 'name',
|
|
3
|
+
email: 'email',
|
|
4
|
+
website: 'url',
|
|
5
|
+
amount: 'currency',
|
|
6
|
+
phone: 'phoneNumber',
|
|
7
|
+
closeAt: 'dateInFuture',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default function fetchData(amountOfRecords) {
|
|
11
|
+
return fetch('https://data-faker.herokuapp.com/collection', {
|
|
12
|
+
method: 'POST',
|
|
13
|
+
headers: {
|
|
14
|
+
'Content-Type': 'application/json; charset=utf-8',
|
|
15
|
+
},
|
|
16
|
+
body: JSON.stringify({
|
|
17
|
+
amountOfRecords,
|
|
18
|
+
recordMetadata,
|
|
19
|
+
}),
|
|
20
|
+
}).then((response) => response.json());
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<p>Total Rows: {data.length}</p>
|
|
3
|
+
<div style="height: 300px;">
|
|
4
|
+
<lightning-datatable
|
|
5
|
+
key-field="id"
|
|
6
|
+
data={data}
|
|
7
|
+
columns={columns}
|
|
8
|
+
enable-infinite-loading
|
|
9
|
+
onloadmore={handleLoadMore}>
|
|
10
|
+
</lightning-datatable>
|
|
11
|
+
</div>
|
|
12
|
+
<p>{loadMoreStatus}</p>
|
|
13
|
+
</template>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { LightningElement } from 'lwc';
|
|
2
|
+
import fetchData from './fetchDataHelper';
|
|
3
|
+
|
|
4
|
+
const columns = [
|
|
5
|
+
{ label: 'Label', fieldName: 'name' },
|
|
6
|
+
{ label: 'Website', fieldName: 'website', type: 'url' },
|
|
7
|
+
{ label: 'Phone', fieldName: 'phone', type: 'phone' },
|
|
8
|
+
{ label: 'Balance', fieldName: 'amount', type: 'currency' },
|
|
9
|
+
{ label: 'CloseAt', fieldName: 'closeAt', type: 'date' },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
export default class DatatableWithInfiniteLoading extends LightningElement {
|
|
13
|
+
data = [];
|
|
14
|
+
columns = columns;
|
|
15
|
+
loadMoreStatus;
|
|
16
|
+
totalNumberOfRows = 250;
|
|
17
|
+
|
|
18
|
+
// eslint-disable-next-line @lwc/lwc/no-async-await
|
|
19
|
+
async connectedCallback() {
|
|
20
|
+
const data = await fetchData(100);
|
|
21
|
+
this.data = data;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// eslint-disable-next-line @lwc/lwc/no-async-await
|
|
25
|
+
async handleLoadMore(event) {
|
|
26
|
+
const datatable = event.target;
|
|
27
|
+
//Displays a spinner to signal that data is being loaded
|
|
28
|
+
datatable.isLoading = true;
|
|
29
|
+
//Displays "Loading" text when more data is being loaded
|
|
30
|
+
this.loadMoreStatus = 'Loading';
|
|
31
|
+
|
|
32
|
+
const newData = await fetchData(50);
|
|
33
|
+
if (this.data.length >= this.totalNumberOfRows) {
|
|
34
|
+
datatable.enableInfiniteLoading = false;
|
|
35
|
+
this.loadMoreStatus = 'No more data to load';
|
|
36
|
+
} else {
|
|
37
|
+
this.data = this.data.concat(newData);
|
|
38
|
+
this.loadMoreStatus = '';
|
|
39
|
+
}
|
|
40
|
+
datatable.isLoading = false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div style="height:160px">
|
|
3
|
+
<lightning-datatable
|
|
4
|
+
key-field="id"
|
|
5
|
+
columns={columns}
|
|
6
|
+
data={data}
|
|
7
|
+
default-sort-direction={defaultSortDirection}
|
|
8
|
+
sorted-direction={sortDirection}
|
|
9
|
+
sorted-by={sortedBy}
|
|
10
|
+
onsort={onHandleSort}
|
|
11
|
+
is-loading={loading}>
|
|
12
|
+
</lightning-datatable>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<lightning-button label="Enable Loading State" onclick={handleLoadingClick}></lightning-button>
|
|
16
|
+
<lightning-button label="Add More Rows" onclick={handleMoreRowsClick}></lightning-button>
|
|
17
|
+
</template>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { LightningElement } from 'lwc';
|
|
2
|
+
|
|
3
|
+
const data = [
|
|
4
|
+
{ id: 1, name: 'Billy Simmons', age: 40, email: 'billy@salesforce.com' },
|
|
5
|
+
{ id: 2, name: 'Kelsey Denesik', age: 35, email: 'kelsey@salesforce.com' },
|
|
6
|
+
{ id: 3, name: 'Kyle Ruecker', age: 50, email: 'kyle@salesforce.com' },
|
|
7
|
+
{
|
|
8
|
+
id: 4,
|
|
9
|
+
name: 'Krystina Kerluke',
|
|
10
|
+
age: 37,
|
|
11
|
+
email: 'krystina@salesforce.com',
|
|
12
|
+
},
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
const actions = [
|
|
16
|
+
{ label: 'Show details', name: 'show_details' },
|
|
17
|
+
{ label: 'Delete', name: 'delete' },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const columns = [
|
|
21
|
+
{ label: 'Name', fieldName: 'name' },
|
|
22
|
+
{
|
|
23
|
+
label: 'Age',
|
|
24
|
+
fieldName: 'age',
|
|
25
|
+
type: 'number',
|
|
26
|
+
sortable: true,
|
|
27
|
+
cellAttributes: { alignment: 'left' },
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
label: 'Email',
|
|
31
|
+
fieldName: 'email',
|
|
32
|
+
type: 'email',
|
|
33
|
+
hideDefaultActions: true,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
type: 'action',
|
|
37
|
+
typeAttributes: { rowActions: actions, menuAlignment: 'right' },
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
export default class DemoApp extends LightningElement {
|
|
42
|
+
data = data;
|
|
43
|
+
columns = columns;
|
|
44
|
+
defaultSortDirection = 'asc';
|
|
45
|
+
sortDirection = 'asc';
|
|
46
|
+
sortedBy;
|
|
47
|
+
loading = false;
|
|
48
|
+
|
|
49
|
+
// Used to sort the 'Age' column
|
|
50
|
+
sortBy(field, reverse, primer) {
|
|
51
|
+
const key = primer
|
|
52
|
+
? function (x) {
|
|
53
|
+
return primer(x[field]);
|
|
54
|
+
}
|
|
55
|
+
: function (x) {
|
|
56
|
+
return x[field];
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return function (a, b) {
|
|
60
|
+
a = key(a);
|
|
61
|
+
b = key(b);
|
|
62
|
+
return reverse * ((a > b) - (b > a));
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
onHandleSort(event) {
|
|
67
|
+
const { fieldName: sortedBy, sortDirection } = event.detail;
|
|
68
|
+
const cloneData = [...this.data];
|
|
69
|
+
|
|
70
|
+
cloneData.sort(this.sortBy(sortedBy, sortDirection === 'asc' ? 1 : -1));
|
|
71
|
+
this.data = cloneData;
|
|
72
|
+
this.sortDirection = sortDirection;
|
|
73
|
+
this.sortedBy = sortedBy;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
handleLoadingClick() {
|
|
77
|
+
this.loading = !this.loading;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
handleMoreRowsClick() {
|
|
81
|
+
const control = [
|
|
82
|
+
{
|
|
83
|
+
id: 20,
|
|
84
|
+
name: 'Jacqueline Palmer',
|
|
85
|
+
age: 60,
|
|
86
|
+
email: 'jacqueline@salesforce.com',
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
this.data = this.data.concat(this.data).concat(control);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const Datatable = require('pageobjects/datatable');
|
|
2
|
+
const Button = require('pageobjects/button');
|
|
3
|
+
|
|
4
|
+
describe('datatable utam test', () => {
|
|
5
|
+
let root;
|
|
6
|
+
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
await browser.url('/datatable/utam');
|
|
9
|
+
root = await $('datatable-utam');
|
|
10
|
+
await root.waitForDisplayed();
|
|
11
|
+
});
|
|
12
|
+
it('should get the cell value by row and column index', async () => {
|
|
13
|
+
const datatable = await utam.load(Datatable, {
|
|
14
|
+
element: await root.shadow$('lightning-datatable'),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const cellValue = await datatable.getCellValueByIndex(1, 2);
|
|
18
|
+
expect(cellValue).toBe('Billy Simmons');
|
|
19
|
+
});
|
|
20
|
+
it('should get the cell value by row index and column label', async () => {
|
|
21
|
+
const datatable = await utam.load(Datatable, {
|
|
22
|
+
element: await root.shadow$('lightning-datatable'),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const cellValue = await datatable.getCellValueByLabel(2, 'Age');
|
|
26
|
+
expect(cellValue).toBe('35');
|
|
27
|
+
});
|
|
28
|
+
it('should get the number of rows in the table', async () => {
|
|
29
|
+
const datatable = await utam.load(Datatable, {
|
|
30
|
+
element: await root.shadow$('lightning-datatable'),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const cellValue = await datatable.getNumRows();
|
|
34
|
+
expect(cellValue).toBe(4);
|
|
35
|
+
});
|
|
36
|
+
it('should tell if the table has any rows', async () => {
|
|
37
|
+
const datatable = await utam.load(Datatable, {
|
|
38
|
+
element: await root.shadow$('lightning-datatable'),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const cellValue = await datatable.hasRows();
|
|
42
|
+
expect(cellValue).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
it('should toggle selection of row - comprehensive', async () => {
|
|
45
|
+
const datatable = await utam.load(Datatable, {
|
|
46
|
+
element: await root.shadow$('lightning-datatable'),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
for (let i = 1; i <= 4; i++) {
|
|
50
|
+
expect(await datatable.isRowSelected(i)).toBe('false');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
await datatable.toggleRowSelection(1);
|
|
54
|
+
expect(await datatable.isRowSelected(1)).toBe('true');
|
|
55
|
+
[2, 3, 4].forEach(async (i) => {
|
|
56
|
+
expect(await datatable.isRowSelected(i)).toBe('false');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await datatable.toggleRowSelection(2);
|
|
60
|
+
expect(await datatable.isRowSelected(2)).toBe('true');
|
|
61
|
+
[3, 4].forEach(async (i) => {
|
|
62
|
+
expect(await datatable.isRowSelected(i)).toBe('false');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
await datatable.toggleRowSelection(3);
|
|
66
|
+
expect(await datatable.isRowSelected(3)).toBe('true');
|
|
67
|
+
expect(await datatable.isRowSelected(4)).toBe('false');
|
|
68
|
+
|
|
69
|
+
await datatable.toggleRowSelection(4);
|
|
70
|
+
expect(await datatable.isRowSelected(4)).toBe('true');
|
|
71
|
+
});
|
|
72
|
+
it('should toggle selection of row', async () => {
|
|
73
|
+
const datatable = await utam.load(Datatable, {
|
|
74
|
+
element: await root.shadow$('lightning-datatable'),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await datatable.toggleRowSelection(3);
|
|
78
|
+
expect(await datatable.isRowSelected(3)).toBe('true');
|
|
79
|
+
|
|
80
|
+
await datatable.toggleRowSelection(3);
|
|
81
|
+
expect(await datatable.isRowSelected(3)).toBe('false');
|
|
82
|
+
});
|
|
83
|
+
it('should get the number of selected rows when not all rows are selected', async () => {
|
|
84
|
+
const datatable = await utam.load(Datatable, {
|
|
85
|
+
element: await root.shadow$('lightning-datatable'),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
await datatable.toggleRowSelection(3);
|
|
89
|
+
expect(await datatable.getNumSelectedRows()).toBe(1);
|
|
90
|
+
|
|
91
|
+
await datatable.toggleRowSelection(2);
|
|
92
|
+
expect(await datatable.getNumSelectedRows()).toBe(2);
|
|
93
|
+
});
|
|
94
|
+
it('should get the number of selected rows when all rows are selected', async () => {
|
|
95
|
+
const datatable = await utam.load(Datatable, {
|
|
96
|
+
element: await root.shadow$('lightning-datatable'),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
await datatable.clickSelectAllCheckbox();
|
|
100
|
+
expect(await datatable.getNumSelectedRows()).toBe(4);
|
|
101
|
+
});
|
|
102
|
+
it('should get the number of columns in the table', async () => {
|
|
103
|
+
const datatable = await utam.load(Datatable, {
|
|
104
|
+
element: await root.shadow$('lightning-datatable'),
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
expect(await datatable.getNumColumns()).toBe(5);
|
|
108
|
+
});
|
|
109
|
+
it('should tell whether or not a column is sortable', async () => {
|
|
110
|
+
const datatable = await utam.load(Datatable, {
|
|
111
|
+
element: await root.shadow$('lightning-datatable'),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
expect(await datatable.isSortableColumn('Age')).toBe(true);
|
|
115
|
+
|
|
116
|
+
// Need to speak to UTAM (about isPresent) or find a better way to write this method
|
|
117
|
+
// If column is not sortable, the test fails with the error:
|
|
118
|
+
// "Can't find elements with locator 'lightning-primitive-header-factory.slds-is-sortable' inside its scope element."
|
|
119
|
+
// expect(await datatable.isSortableColumn('Name')).toBe(false);
|
|
120
|
+
});
|
|
121
|
+
it('should tell whether or not the row is selectable', async () => {
|
|
122
|
+
const datatable = await utam.load(Datatable, {
|
|
123
|
+
element: await root.shadow$('lightning-datatable'),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
expect(await datatable.isSelectableRow(1)).toBe(true);
|
|
127
|
+
});
|
|
128
|
+
it('should get the width of a column', async () => {
|
|
129
|
+
const datatable = await utam.load(Datatable, {
|
|
130
|
+
element: await root.shadow$('lightning-datatable'),
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const dt = await root.shadow$('lightning-datatable');
|
|
134
|
+
const columnHeader = await dt.shadow$('thead > tr > th:nth-child(2)');
|
|
135
|
+
const expectedWidth = await columnHeader.getAttribute('style');
|
|
136
|
+
expect(await datatable.getWidth('Name')).toBe(expectedWidth);
|
|
137
|
+
});
|
|
138
|
+
it('should tell whether or not a column has header actions', async () => {
|
|
139
|
+
const datatable = await utam.load(Datatable, {
|
|
140
|
+
element: await root.shadow$('lightning-datatable'),
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
expect(await datatable.hasHeaderActions('Name')).toBe(true);
|
|
144
|
+
expect(await datatable.hasHeaderActions('Age')).toBe(true);
|
|
145
|
+
// false fails; need to check for true or null; check with UTAM if expected
|
|
146
|
+
expect(await datatable.hasHeaderActions('Email')).toBe(null);
|
|
147
|
+
});
|
|
148
|
+
it('should get the text of the rowheader cell of the specified row', async () => {
|
|
149
|
+
const datatable = await utam.load(Datatable, {
|
|
150
|
+
element: await root.shadow$('lightning-datatable'),
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
expect(await datatable.getRowHeaderText(2)).toBe('Kelsey Denesik');
|
|
154
|
+
});
|
|
155
|
+
it('should click column header of the sortable column', async () => {
|
|
156
|
+
const datatable = await utam.load(Datatable, {
|
|
157
|
+
element: await root.shadow$('lightning-datatable'),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
let cellValue = await datatable.getCellValueByLabel(1, 'Age');
|
|
161
|
+
expect(cellValue).toBe('40');
|
|
162
|
+
|
|
163
|
+
await datatable.clickSortHeaderButton('Age');
|
|
164
|
+
|
|
165
|
+
cellValue = await datatable.getCellValueByLabel(1, 'Age');
|
|
166
|
+
expect(cellValue).toBe('35');
|
|
167
|
+
});
|
|
168
|
+
it('should tell whether the specified row has row actions or not', async () => {
|
|
169
|
+
const datatable = await utam.load(Datatable, {
|
|
170
|
+
element: await root.shadow$('lightning-datatable'),
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
expect(await datatable.hasRowActionInRow(2)).toBe(true);
|
|
174
|
+
});
|
|
175
|
+
it('should tell whether or not the datatable has the loading indicator visible', async () => {
|
|
176
|
+
const datatable = await utam.load(Datatable, {
|
|
177
|
+
element: await root.shadow$('lightning-datatable'),
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
expect(await datatable.isLoading()).toBe(false);
|
|
181
|
+
|
|
182
|
+
const button = await utam.load(Button, {
|
|
183
|
+
element: await root.shadow$('lightning-button'),
|
|
184
|
+
});
|
|
185
|
+
await button.click();
|
|
186
|
+
|
|
187
|
+
expect(await datatable.isLoading()).toBe(true);
|
|
188
|
+
});
|
|
189
|
+
});
|