lightning-base-components 1.16.3-alpha → 1.16.5-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/README.md +7 -0
- package/metadata/raptor.json +110 -0
- package/package.json +59 -2
- package/scopedImports/@salesforce-label-LightningForm.cancel.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.closeError.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.edit.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.editErrorHelp.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.error.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.errorPopoverHeading.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.preview.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.previewHeader.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.reload.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.save.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.saveFieldErrorSummary.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.undo.js +1 -0
- package/scopedImports/@salesforce-label-LightningLookup.messageWhenMissingInformation.js +1 -0
- package/src/lightning/button/__docs__/button.md +13 -0
- package/src/lightning/button/button.slds.css +155 -11
- package/src/lightning/buttonGroup/button-group.slds.css +35 -59
- package/src/lightning/buttonIcon/button-icon.slds.css +287 -122
- package/src/lightning/buttonIconStateful/button-icon-stateful.slds.css +224 -39
- package/src/lightning/buttonStateful/button-stateful.slds.css +3269 -0
- package/src/lightning/card/card.slds.css +50 -0
- package/src/lightning/colorPickerCustom/color-picker-custom.slds.css +180 -364
- package/src/lightning/colorPickerPanel/color-picker-panel.slds.css +46 -413
- package/src/lightning/datatable/datatable.js +2 -2
- package/src/lightning/datatable/rowSelection.js +21 -4
- package/src/lightning/datetimepicker/datetimepicker.html +1 -3
- package/src/lightning/datetimepicker/datetimepicker.js +5 -0
- package/src/lightning/fileDownload/__docs__/fileDownload.md +41 -0
- package/src/lightning/helptext/help-text.slds.css +184 -39
- package/src/lightning/icon/icon.slds.css +823 -3
- package/src/lightning/input/input-checkbox.slds.css +291 -32
- package/src/lightning/input/input-text.slds.css +70 -7
- package/src/lightning/inputAddress/__docs__/inputAddress.md +1 -1
- package/src/lightning/inputAddress/inputAddress.js +2 -1
- package/src/lightning/internationalizationLibrary/datetime/intlFormat.js +20 -2
- package/src/lightning/iso8601Utils/iso8601Utils.js +2 -3
- package/src/lightning/mediaUtils/__docs__/mediaUtils.md +87 -0
- package/src/lightning/mediaUtils/mediaUtils.js +321 -0
- package/src/lightning/mediaUtils/mediaUtils.js-meta.xml +6 -0
- package/src/lightning/modal/__docs__/migration.md +158 -0
- package/src/lightning/modal/__docs__/modal.md +414 -0
- package/src/lightning/modal/__examples__disabled/all/all.css +7 -0
- package/src/lightning/modal/__examples__disabled/all/all.html +9 -0
- package/src/lightning/modal/__examples__disabled/all/all.js +25 -0
- package/src/lightning/modal/__examples__disabled/allform/allform.css +7 -0
- package/src/lightning/modal/__examples__disabled/allform/allform.html +9 -0
- package/src/lightning/modal/__examples__disabled/allform/allform.js +49 -0
- package/src/lightning/modal/__examples__disabled/allmulti/allmulti.html +24 -0
- package/src/lightning/modal/__examples__disabled/allmulti/allmulti.js +12 -0
- package/src/lightning/modal/__examples__disabled/basic/basic.css +7 -0
- package/src/lightning/modal/__examples__disabled/basic/basic.html +9 -0
- package/src/lightning/modal/__examples__disabled/basic/basic.js +27 -0
- package/src/lightning/modal/__examples__disabled/demo/demo.html +15 -0
- package/src/lightning/modal/__examples__disabled/demo/demo.js +13 -0
- package/src/lightning/modal/__examples__disabled/demoall/demoall.html +26 -0
- package/src/lightning/modal/__examples__disabled/demoall/demoall.js +13 -0
- package/src/lightning/modal/__examples__disabled/demoallform/demoallform.css +3 -0
- package/src/lightning/modal/__examples__disabled/demoallform/demoallform.html +146 -0
- package/src/lightning/modal/__examples__disabled/demoallform/demoallform.js +240 -0
- package/src/lightning/modal/__examples__disabled/demofootless/demofootless.html +17 -0
- package/src/lightning/modal/__examples__disabled/demofootless/demofootless.js +11 -0
- package/src/lightning/modal/__examples__disabled/demoheadless/demoheadless.html +20 -0
- package/src/lightning/modal/__examples__disabled/demoheadless/demoheadless.js +12 -0
- package/src/lightning/modal/__examples__disabled/footless/footless.css +7 -0
- package/src/lightning/modal/__examples__disabled/footless/footless.html +9 -0
- package/src/lightning/modal/__examples__disabled/footless/footless.js +19 -0
- package/src/lightning/modal/__examples__disabled/headless/headless.css +7 -0
- package/src/lightning/modal/__examples__disabled/headless/headless.html +9 -0
- package/src/lightning/modal/__examples__disabled/headless/headless.js +27 -0
- package/src/lightning/modal/modal.html +3 -0
- package/src/lightning/modal/modal.js +93 -0
- package/src/lightning/modal/modal.js-meta.xml +6 -0
- package/src/lightning/modalBody/__docs__/modalBody.md +61 -0
- package/src/lightning/modalBody/modalBody.html +13 -0
- package/src/lightning/modalBody/modalBody.js +203 -0
- package/src/lightning/modalBody/modalBody.js-meta.xml +6 -0
- package/src/lightning/modalFooter/__docs__/modalFooter.md +72 -0
- package/src/lightning/modalFooter/modalFooter.html +8 -0
- package/src/lightning/modalFooter/modalFooter.js +161 -0
- package/src/lightning/modalFooter/modalFooter.js-meta.xml +6 -0
- package/src/lightning/modalHeader/__docs__/modalHeader.md +64 -0
- package/src/lightning/modalHeader/modalHeader.html +16 -0
- package/src/lightning/modalHeader/modalHeader.js +204 -0
- package/src/lightning/modalHeader/modalHeader.js-meta.xml +6 -0
- package/src/lightning/primitiveBubble/tooltip.slds.css +45 -1
- package/src/lightning/primitiveCellFactory/primitiveCellFactory.js +4 -12
- package/src/lightning/primitiveColorpickerButton/color-picker-button.slds.css +2994 -319
- package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.html +14 -11
- package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.js +1 -0
- package/src/lightning/primitiveIcon/icon.slds.css +823 -3
- package/src/lightning/progressStep/base.html +1 -0
- package/src/lightning/progressStep/path.html +1 -1
- package/src/lightning/radioGroup/input-radio-group.slds.css +168 -379
- package/src/lightning/spinner/spinner.slds.css +8 -2
- package/src/lightning/timepicker/timepicker.html +1 -4
- package/src/lightning/timepicker/timepicker.js +9 -5
- package/src/lightning/treeGrid/treeGrid.js +66 -1
- package/src/lightning/utilsPrivate/linkUtils.js +1 -1
- package/src/lightning/formattedAddress/__component__/formattedAddress.spec.js +0 -61
- package/src/lightning/formattedAddress/__component__/formattedAddressDisabled.spec.js +0 -20
- package/src/lightning/formattedAddress/__component__/x/basic/basic.html +0 -10
- package/src/lightning/formattedAddress/__component__/x/basic/basic.js +0 -17
- package/src/lightning/input/__component__/inputCheckbox.spec.js +0 -60
- package/src/lightning/input/__component__/inputDateTimePicker.spec.js +0 -60
- package/src/lightning/input/__component__/inputNumber.spec.js +0 -75
- package/src/lightning/input/__component__/inputSelection.spec.js +0 -83
- package/src/lightning/input/__component__/x/tall/tall.css +0 -5
- package/src/lightning/input/__component__/x/tall/tall.html +0 -5
- package/src/lightning/input/__component__/x/tall/tall.js +0 -7
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
A `lightningModal` component overlays a message modal on top of the current app window. A modal interrupts a user’s workflow and draws attention to the message.
|
|
2
|
+
|
|
3
|
+
`LightningModal` implements the SLDS [modals](https://www.lightningdesignsystem.com/components/modals/) blueprint.
|
|
4
|
+
|
|
5
|
+
Create a modal component in response to a user action, such as clicking a button or link. The modal blocks interaction with everything else on the page until the user acts upon or dismisses the modal.
|
|
6
|
+
|
|
7
|
+
Unlike other components, this component doesn't use a `lightning-modal` tag or extend `LightningElement`. There is no `lightning-modal` component. Instead, you create a modal by extending `LightningModal` and using these helper `lightning-modal-*` components to provide a header, footer and the body of the modal.
|
|
8
|
+
- `lightning-modal-body`
|
|
9
|
+
- `lightning-modal-header`
|
|
10
|
+
- `lightning-modal-footer`
|
|
11
|
+
|
|
12
|
+
To create a modal component, import `LightningModal` from `lightning/modal`. The component has access to the normal LWC resources as well as the special container, helper components, methods, and events of the `lightning/modal` module.
|
|
13
|
+
|
|
14
|
+
In this example, the `content` property passes data to the modal from the component that invokes it.
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
/* c/myModal.js */
|
|
18
|
+
|
|
19
|
+
import { api } from 'lwc';
|
|
20
|
+
import LightningModal from 'lightning/modal';
|
|
21
|
+
|
|
22
|
+
export default class MyModal extends LightningModal {
|
|
23
|
+
@api content;
|
|
24
|
+
|
|
25
|
+
handleOkay() {
|
|
26
|
+
this.close('okay');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The modal’s HTML template uses helper `lightning-modal-*` components to provide a header, footer, and the body of the modal. In this example, the content for the modal body comes from the `content` property we defined in the modal's JavaScript file.
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<!-- c/myModal.html -->
|
|
35
|
+
|
|
36
|
+
<template>
|
|
37
|
+
<lightning-modal-header label="My Modal Heading"></lightning-modal-header>
|
|
38
|
+
<lightning-modal-body> Content: {content} </lightning-modal-body>
|
|
39
|
+
<lightning-modal-footer>
|
|
40
|
+
<lightning-button label="OK" onclick={handleOkay}></lightning-button>
|
|
41
|
+
</lightning-modal-footer>
|
|
42
|
+
</template>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The `lightning-modal-body` component is required for the modal template.
|
|
46
|
+
|
|
47
|
+
The `lightning-modal-header` and `lightning-modal-footer` components are optional, but recommended. The `lightning-modal-*` components render in the order they appear in the template. Place the `lightning-modal-body` component after `lightning-modal-header` and before the `lightning-modal-footer` component.
|
|
48
|
+
|
|
49
|
+
#### Open a Modal Instance
|
|
50
|
+
|
|
51
|
+
`LightningModal` provides an `.open()` method which opens a modal and returns a promise that asynchronously resolves with the result of the user’s interaction with the modal.
|
|
52
|
+
|
|
53
|
+
Each invocation of a modal component’s `.open()` method creates a unique instance of the modal. You can think of a modal as a self-contained application that starts from scratch when it opens. It displays the content you pass in through the `.open()` method or that you set within the modal's HTML template.
|
|
54
|
+
|
|
55
|
+
When you close a modal, the modal instance is destroyed, not hidden. On close, the modal must save the user’s input data or pass it to the invoking component as the promise result. Otherwise, the data is lost when the modal instance is closed.
|
|
56
|
+
|
|
57
|
+
The `.open()` method lets you assign values to the modal's properties. `LightningModal` provides these properties.
|
|
58
|
+
|
|
59
|
+
* `label` - Required. Sets the modal's title and assistive device label. If the modal has a header, set `label` in the `lightning-modal-header` component. If the modal doesn't have a header, set the `label` property when opening the modal.
|
|
60
|
+
|
|
61
|
+
* `size` - Determines how much of the viewport width the modal uses. Supported values are `small`, `medium`, and `large`, which you can set when you open the modal. Default value is `medium`. The length of the modal is determined by the amount of content.
|
|
62
|
+
|
|
63
|
+
* `description` - Sets the modal's accessible description. It uses the `aria-description` attribute where supported, or falls back to `aria-describedby`. If you set a custom description value, include the label name at the beginning of your description, because some screen readers only read the description, and not the label.
|
|
64
|
+
|
|
65
|
+
* `disableClose` - Prevents closing the modal by normal means like the ESC key, the close button, or `.close()`. For example, you could briefly set `disableClose` to true while a completed form is saving, so the user doesn't dismiss the modal early. See [**Use the `disableClose` Attribute**](#use-the-disableclose-attribute).
|
|
66
|
+
|
|
67
|
+
In this example, the app opens the `myModal` component. It invokes the `.open()` method in a `handleClick()` function bound to the app button’s `onclick` attribute, and uses `async` and `await` keywords to handle the promise returned by `.open()`. This example overrides the `size` value by setting it to `large` and sets the modal’s user-defined property `content`.
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
/* c/myApp.js */
|
|
71
|
+
|
|
72
|
+
import { LightningElement } from 'lwc';
|
|
73
|
+
import MyModal from 'c/myModal';
|
|
74
|
+
|
|
75
|
+
export default class MyApp extends LightningElement {
|
|
76
|
+
async handleClick() {
|
|
77
|
+
const result = await MyModal.open({
|
|
78
|
+
// `label` is not included here in this example.
|
|
79
|
+
// it is set on lightning-modal-header instead
|
|
80
|
+
size: 'large',
|
|
81
|
+
description: 'Accessible description of modal\'s purpose',
|
|
82
|
+
content: 'Passed into content api',
|
|
83
|
+
});
|
|
84
|
+
// if modal closed with X button, promise returns result = 'undefined'
|
|
85
|
+
// if modal closed with OK button, promise returns result = 'okay'
|
|
86
|
+
console.log(result);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
The HTML template for this app contains a button that opens the modal and displays the result returned when the modal closes.
|
|
91
|
+
|
|
92
|
+
```html
|
|
93
|
+
<!-- c/myApp.html -->
|
|
94
|
+
|
|
95
|
+
<template>
|
|
96
|
+
<lightning-button
|
|
97
|
+
onclick={handleClick}
|
|
98
|
+
aria-haspopup="modal"
|
|
99
|
+
label="Open My Modal">
|
|
100
|
+
</lightning-button>
|
|
101
|
+
<p>Result: {result}</p>
|
|
102
|
+
</template>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
You can also use `.open()` to pass data from your invoking component into the modal with custom properties decorated with `@api`. These properties can be any type, such as a string or an object that’s an array of key/value pairs to be assigned to the new modal instance.
|
|
106
|
+
|
|
107
|
+
For example, this app component sets an `options` property to a set of key/value pairs in `MyModal.open()`. The promise is handled using an arrow function that logs the result to the console.
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
/* c/myApp.js */
|
|
111
|
+
|
|
112
|
+
import { LightningElement } from "lwc";
|
|
113
|
+
import MyModal from "c/myModal";
|
|
114
|
+
|
|
115
|
+
export default class MyPage extends LightningElement {
|
|
116
|
+
handleOpenClick() {
|
|
117
|
+
MyModal.open({
|
|
118
|
+
// maps to developer-created `@api options`
|
|
119
|
+
options: [
|
|
120
|
+
{ id: 1, label: 'Option 1' },
|
|
121
|
+
{ id: 2, label: 'Option 2' },
|
|
122
|
+
]
|
|
123
|
+
}).then((result) => {
|
|
124
|
+
console.log(result);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
The modal dialog can then use this property. In this case, the modal creates buttons whose labels are provided in the `options` array.
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
/* c/myModal.js */
|
|
133
|
+
|
|
134
|
+
import { api } from 'lwc';
|
|
135
|
+
import LightningModal from 'lightning/modal';
|
|
136
|
+
|
|
137
|
+
export default class MyModal extends LightningModal {
|
|
138
|
+
// Data is passed to api properties via .open({ options: [] })
|
|
139
|
+
@api options = [];
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
```html
|
|
144
|
+
<!-- c/myModal.html -->
|
|
145
|
+
|
|
146
|
+
<template>
|
|
147
|
+
<lightning-modal-header label="My Modal Heading"></lightning-modal-header>
|
|
148
|
+
<lightning-modal-body>
|
|
149
|
+
Let's make some buttons!
|
|
150
|
+
<template for:each={options} for:item="option">
|
|
151
|
+
<lightning-button
|
|
152
|
+
onclick={handleOptionClick}
|
|
153
|
+
data-id={option.id}
|
|
154
|
+
key={option.id}
|
|
155
|
+
>
|
|
156
|
+
{option.label}
|
|
157
|
+
</lightning-button>
|
|
158
|
+
</template>
|
|
159
|
+
</lightning-modal-body>
|
|
160
|
+
</template>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### Close a Modal Instance
|
|
164
|
+
|
|
165
|
+
Use `this.close(result)` to close the modal, where `result` is anything you want to return from the modal. The `.close()` operation is asynchronous to display a brief fade out animation before the modal is destroyed. The `result` data can’t be modified after the close operation begins.
|
|
166
|
+
|
|
167
|
+
You can also close the modal with the default close button, the X at the top right corner. Closing a modal like this is the same as calling `this.close()` with an `undefined` result, so any data input is lost.
|
|
168
|
+
|
|
169
|
+
This example shows the handler for some buttons inside a modal. When the user clicks the button, `this.close(id)` returns the option that they chose and the modal closes.
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
/* c/myModal.js */
|
|
173
|
+
|
|
174
|
+
import { api } from 'lwc';
|
|
175
|
+
import LightningModal from 'lightning/modal';
|
|
176
|
+
|
|
177
|
+
export default class MyModal extends LightningModal {
|
|
178
|
+
// Data is passed to apis via .open({ options: [] })
|
|
179
|
+
@api options = [];
|
|
180
|
+
|
|
181
|
+
handleOptionClick(e) {
|
|
182
|
+
const { target } = e;
|
|
183
|
+
const { id } = target.dataset;
|
|
184
|
+
// this.close() triggers closing the modal
|
|
185
|
+
// the value of `id` is passed as the result
|
|
186
|
+
this.close(id);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
```html
|
|
192
|
+
<!-- c/myModal.html -->
|
|
193
|
+
|
|
194
|
+
<template>
|
|
195
|
+
<template for:each={options} for:item="option">
|
|
196
|
+
<lightning-button
|
|
197
|
+
onclick={handleOptionClick}
|
|
198
|
+
data-id={option.id}
|
|
199
|
+
key={option.id}
|
|
200
|
+
>
|
|
201
|
+
{option.label}
|
|
202
|
+
</lightning-button>
|
|
203
|
+
</template>
|
|
204
|
+
</template>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### Use the `disableClose` Attribute
|
|
208
|
+
|
|
209
|
+
`disableClose` temporarily turns off the ability to dismiss the modal by normal means like the ESC key, the close button, or `this.close()`. For example, you could briefly set `disableClose` to `true` while a completed form is saving, so the user doesn't dismiss the modal early.
|
|
210
|
+
|
|
211
|
+
Preventing a modal's close should be a temporary state. Use `disableClose` for less than 5 seconds. Accessibility is affected if you trap keyboard focus inappropriately. See [No Keyboard Trap](https://www.w3.org/TR/UNDERSTANDING-WCAG20/keyboard-operation-trapping.html) for more information.
|
|
212
|
+
|
|
213
|
+
When the process using `disableClose` finishes successfully, dismiss the modal. If the process using `disableClose` fails, re-enable the ability to dismiss the modal with `disableClose = false`, or give feedback to help the user resolve the issue.
|
|
214
|
+
|
|
215
|
+
While `disableClose` is `true`, disable any processes or UI buttons that might call `Modal.close()`.
|
|
216
|
+
|
|
217
|
+
This example shows how to use `disableClose`. It's not a fully functional example, but could be used in a complex modal component.
|
|
218
|
+
|
|
219
|
+
```js
|
|
220
|
+
/* c/myModalForm.js */
|
|
221
|
+
/* This is intended as a mock example, not as fully functional code */
|
|
222
|
+
/* NOTE: observe values set:
|
|
223
|
+
this.disableClose (in JS),
|
|
224
|
+
and this.saveInProcess (in JS and HTML)
|
|
225
|
+
*/
|
|
226
|
+
import { api } from 'lwc';
|
|
227
|
+
import LightningModal from 'lightning/modal';
|
|
228
|
+
|
|
229
|
+
export default class MyModalForm extends LightningModal {
|
|
230
|
+
// formData is utilized for saving current form values
|
|
231
|
+
formData = {};
|
|
232
|
+
failureType = null;
|
|
233
|
+
saveStatus = {};
|
|
234
|
+
saveInProcess = false;
|
|
235
|
+
|
|
236
|
+
handleCloseClick() {
|
|
237
|
+
this.close('canceled');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
closeModal() {
|
|
241
|
+
// immediately exits, so no need to trigger
|
|
242
|
+
// this.disableClose = false OR
|
|
243
|
+
// this.saveInProcess = false;
|
|
244
|
+
// modal is destroyed, and focus moves
|
|
245
|
+
// back to originally clicked item that
|
|
246
|
+
// generated the modal
|
|
247
|
+
this.close('success');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
mitigateSaveFailure() {
|
|
251
|
+
// depending on how easily the failure can be resolved
|
|
252
|
+
// you may need to immediately set disableClose = false
|
|
253
|
+
if (this.failureType === 'recoverable') {
|
|
254
|
+
// no need to call this.disableClose = false
|
|
255
|
+
// or this.saveInProgress = false yet
|
|
256
|
+
tryToFixFailure();
|
|
257
|
+
} else {
|
|
258
|
+
// can't resolve the error
|
|
259
|
+
// need to allow users to exit modal
|
|
260
|
+
this.disableClose = false;
|
|
261
|
+
this.saveInProcess = false;
|
|
262
|
+
// mock function to indicate modal state
|
|
263
|
+
// while still allowing user to exit
|
|
264
|
+
// preventing keyboard trap
|
|
265
|
+
reportUnresolvableError();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async saveData() {
|
|
270
|
+
// switches disabled state on buttons
|
|
271
|
+
this.saveInProcess = true;
|
|
272
|
+
const saveStatus = await sendData(this.formData);
|
|
273
|
+
return (saveStatus && saveStatus.success)
|
|
274
|
+
? closeModal()
|
|
275
|
+
: mitigateSaveFailure();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async handleSaveClick() {
|
|
279
|
+
if (isValid(this.formData)) {
|
|
280
|
+
// begin saving data, temporarily disable
|
|
281
|
+
// LightningModal's close button
|
|
282
|
+
// Be sure to reenable the close button, by setting
|
|
283
|
+
// this.disableClose = false, IF further interaction
|
|
284
|
+
// is desired before the modal closes
|
|
285
|
+
this.disableClose = true;
|
|
286
|
+
await saveData();
|
|
287
|
+
} else {
|
|
288
|
+
// function that display form errors based on data
|
|
289
|
+
showFormErrors(this.formData);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
```html
|
|
296
|
+
<!-- c/myModalForm.html -->
|
|
297
|
+
|
|
298
|
+
<template>
|
|
299
|
+
<lightning-modal-header
|
|
300
|
+
label="My Modal Heading"
|
|
301
|
+
></lightning-modal-header>
|
|
302
|
+
<lightning-modal-body>
|
|
303
|
+
<!-- form here -->
|
|
304
|
+
</lightning-modal-body>
|
|
305
|
+
<lightning-modal-footer>
|
|
306
|
+
<button
|
|
307
|
+
disabled={saveInProcess}
|
|
308
|
+
onclick={handleCloseClick}
|
|
309
|
+
aria-label="Cancel and close"
|
|
310
|
+
>Cancel</button>
|
|
311
|
+
<button
|
|
312
|
+
disabled={saveInProcess}
|
|
313
|
+
onclick={handleSaveClick}
|
|
314
|
+
>Save</button>
|
|
315
|
+
</lightning-modal-footer>
|
|
316
|
+
</template>
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
#### Modal Events
|
|
320
|
+
|
|
321
|
+
A modal can only fire events captured by the component that opened it, not the modal itself. Normal techniques can't catch events that fire from the modal, because the events bubble up to a top root element outside of the component that opened the modal.
|
|
322
|
+
|
|
323
|
+
To capture modal events, attach them in the `.open()` method invoked by the component that opens the modal.
|
|
324
|
+
|
|
325
|
+
For example, here's a custom `select` event dispatched from `MyModal`.
|
|
326
|
+
|
|
327
|
+
```js
|
|
328
|
+
/* c/myModal.js */
|
|
329
|
+
dispatchSelectEvent(e) {
|
|
330
|
+
// e.target might represent an input with an id and value
|
|
331
|
+
const { id, value } = e.target;
|
|
332
|
+
const selectEvent = new CustomEvent('select', {
|
|
333
|
+
detail: { id, value }
|
|
334
|
+
});
|
|
335
|
+
this.dispatchEvent(selectEvent);
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
The `open()` method in `myApp` defines the `onselect` event handler. This example uses `onselect` to proxy events that we want to pass through.
|
|
340
|
+
|
|
341
|
+
```js
|
|
342
|
+
/* c/myApp.js */
|
|
343
|
+
|
|
344
|
+
// ...
|
|
345
|
+
// Process the select event from within the modal
|
|
346
|
+
handleSelectEvent(detail) {
|
|
347
|
+
const { id, value } = detail;
|
|
348
|
+
console.log(`select event fired elem with id ${id} and value: ${value}`);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// ...
|
|
352
|
+
// Trigger visibility of the modal
|
|
353
|
+
handleOpenModal() {
|
|
354
|
+
MyModal.open({
|
|
355
|
+
label: 'Modal Title',
|
|
356
|
+
size: 'large',
|
|
357
|
+
description: 'Modal Title with brief description',
|
|
358
|
+
// event triggered when new CustomEvent('select', {detail: {}});
|
|
359
|
+
// occurs *from within* LightningModal.
|
|
360
|
+
// see dispatchSelectEvent() in c/myModal.js above
|
|
361
|
+
onselect: (e) => {
|
|
362
|
+
// stop further propagation of the event
|
|
363
|
+
e.stopPropagation();
|
|
364
|
+
// hand off to separate function to process
|
|
365
|
+
// result of the event (see above in this example)
|
|
366
|
+
this.handleSelectEvent(e.detail);
|
|
367
|
+
// or proxy to be handled above by dispatching
|
|
368
|
+
// another custom event to pass on the event
|
|
369
|
+
// this.dispatchEvent(e);
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
See [Create and Dispatch Events](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/events_create_dispatch) in the LWC Dev Guide for more information about events.
|
|
376
|
+
|
|
377
|
+
#### Styling Variants
|
|
378
|
+
|
|
379
|
+
The `lightning-modal-header` and `lightning-modal-footer` child components are optional, and you can choose to not include one or the other in your modal.
|
|
380
|
+
|
|
381
|
+
The headerless variant of `LightningModal` has these additional requirements.
|
|
382
|
+
- Must set a descriptive modal title with the `label` property using `Modal.open({ label })` or you’ll get a console error.
|
|
383
|
+
- The `label` property is required for all variants of `LightningModal`. Assistive devices read the `label` value, even though the headerless modal variant doesn't display the label.
|
|
384
|
+
- Because this variant doesn't use `lightning-modal-header`, you have to manually create an `<h1>` heading in `lightning-modal-body`. Provide accessible structure by starting with heading level `<h1>` and using levels up to `<h6>` appropriately. For more information, see [Semantic Structure, Headings on WebAim.org](https://webaim.org/techniques/semanticstructure/#headings).
|
|
385
|
+
|
|
386
|
+
The `LightningModal` component also supports the SLDS [Directional variant](https://www.lightningdesignsystem.com/components/modals/#Directional) modal blueprint pattern.
|
|
387
|
+
|
|
388
|
+
To achieve the directional button layout, place the buttons in a `div` with the `slds-modal__footer_directional` class.
|
|
389
|
+
|
|
390
|
+
```html
|
|
391
|
+
<!-- c/modalDirectional.html -->
|
|
392
|
+
|
|
393
|
+
<template>
|
|
394
|
+
<lightning-modal-body> Content: {content} </lightning-modal-body>
|
|
395
|
+
<lightning-modal-footer>
|
|
396
|
+
<div class=“slds-modal__footer_directional”>
|
|
397
|
+
<lightning-button label="NO" onclick={handleNo}></lightning-button>
|
|
398
|
+
<lightning-button label="OK" onclick={handleOkay}></lightning-button>
|
|
399
|
+
</div>
|
|
400
|
+
</lightning-modal-footer>
|
|
401
|
+
</template>
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
#### Styling Hooks
|
|
405
|
+
|
|
406
|
+
The `lightning-modal-*` helper components support [style hooks](https://www.lightningdesignsystem.com/components/modals/#Styling-Hooks-Overview). The styling hooks for the template that invokes the helper components doesn't carry over to them, so you must style each helper component individually.
|
|
407
|
+
|
|
408
|
+
Customizing the styling on the white modal frame and background, close button, or gray backdrop isn't supported.
|
|
409
|
+
|
|
410
|
+
#### Accessibility
|
|
411
|
+
|
|
412
|
+
The `lightning-modal-header` component renders the `label` value in an `<h1>` element. If your modal uses the header, begin any additional heading levels in the modal with `<h2>` for accessibility. Provide accessible structure by using heading levels up to `<h6>` appropriately. For more information, see [Semantic Structure, Headings on WebAim.org](https://webaim.org/techniques/semanticstructure/#headings).
|
|
413
|
+
|
|
414
|
+
To include tagline text or link content for the header section, add it between the `<lightning-modal-header>` tags.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { LightningElement } from 'lwc';
|
|
2
|
+
import ModalDemoAll from 'modal/demoall';
|
|
3
|
+
|
|
4
|
+
export default class ModalAll extends LightningElement {
|
|
5
|
+
demoResult = 'unset';
|
|
6
|
+
|
|
7
|
+
handleDemoModal() {
|
|
8
|
+
ModalDemoAll.open({
|
|
9
|
+
// LightningModal
|
|
10
|
+
size: 'small',
|
|
11
|
+
// ModalDemo
|
|
12
|
+
options: [
|
|
13
|
+
{ id: 1, variant: 'neutral', label: 'Option 1' },
|
|
14
|
+
{ id: 2, variant: 'neutral', label: 'Option 2' },
|
|
15
|
+
{ id: 3, variant: 'brand', label: 'Main Option' },
|
|
16
|
+
],
|
|
17
|
+
}).then((result) => {
|
|
18
|
+
if (result === null) {
|
|
19
|
+
this.demoResult = 'dismiss';
|
|
20
|
+
} else {
|
|
21
|
+
this.demoResult = result;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { LightningElement } from 'lwc';
|
|
2
|
+
import ModalDemoAllForm from 'modal/demoallform';
|
|
3
|
+
|
|
4
|
+
export default class ModalAllForm extends LightningElement {
|
|
5
|
+
demoResult = 'unset';
|
|
6
|
+
|
|
7
|
+
handleDemoModal() {
|
|
8
|
+
ModalDemoAllForm.open({
|
|
9
|
+
// LightningModal
|
|
10
|
+
size: 'small',
|
|
11
|
+
// this becomes 'label'
|
|
12
|
+
heading: 'Edit Contact Information',
|
|
13
|
+
description: 'Edit the contact information for Sales Opportunities',
|
|
14
|
+
// ModalDemo
|
|
15
|
+
options: [
|
|
16
|
+
{
|
|
17
|
+
id: 1,
|
|
18
|
+
variant: 'neutral',
|
|
19
|
+
label: 'Close',
|
|
20
|
+
triggerCancel: true,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: 2,
|
|
24
|
+
variant: 'neutral',
|
|
25
|
+
label: 'Disable Close Button',
|
|
26
|
+
toggleDisableClose: true,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 3,
|
|
30
|
+
variant: 'neutral',
|
|
31
|
+
label: 'Open Next Modal',
|
|
32
|
+
triggerSecondModal: true,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 4,
|
|
36
|
+
variant: 'brand',
|
|
37
|
+
label: 'Save Data',
|
|
38
|
+
triggerSubmit: true,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
}).then((result) => {
|
|
42
|
+
if (result === null) {
|
|
43
|
+
this.demoResult = 'dismiss';
|
|
44
|
+
} else {
|
|
45
|
+
this.demoResult = JSON.stringify(result);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<lightning-modal-header label={heading}></lightning-modal-header>
|
|
3
|
+
<lightning-modal-body><div id="all-body">
|
|
4
|
+
<p>Sit nulla est ex deserunt exercitation anim occaecat. Nostrud ullamco deserunt aute id consequat veniam incididunt duis in sint irure nisi. Mollit officia cillum Lorem ullamco minim nostrud elit officia tempor esse quis. Cillum sunt ad dolore quis
|
|
5
|
+
aute consequat ipsum magna exercitation reprehenderit magna. Tempor cupidatat consequat elit dolor adipisicing.</p>
|
|
6
|
+
<p>Dolor eiusmod sunt ex incididunt cillum quis nostrud velit duis sit officia.
|
|
7
|
+
Lorem aliqua enim laboris do dolor eiusmod officia. Mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident. Eiusmod et adipisicing culpa deserunt nostrud
|
|
8
|
+
ad veniam nulla aute est. Labore esse esse cupidatat amet velit id elit consequat
|
|
9
|
+
minim ullamco mollit enim excepteur ea.</p>
|
|
10
|
+
</div></lightning-modal-body>
|
|
11
|
+
<lightning-modal-footer><div id="all-footer">
|
|
12
|
+
<template for:each={options} for:item="option">
|
|
13
|
+
<lightning-button
|
|
14
|
+
key={option.id}
|
|
15
|
+
label={option.label}
|
|
16
|
+
class="slds-button"
|
|
17
|
+
data-focus={option.focusName}
|
|
18
|
+
variant={option.variant}
|
|
19
|
+
onclick={handleOptionClick}
|
|
20
|
+
data-id={option.id}
|
|
21
|
+
></lightning-button>
|
|
22
|
+
</template>
|
|
23
|
+
</div></lightning-modal-footer>
|
|
24
|
+
</template>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { api } from 'lwc';
|
|
2
|
+
import LightningModal from 'lightning/modal';
|
|
3
|
+
|
|
4
|
+
export default class ModalAllMulti extends LightningModal {
|
|
5
|
+
@api heading = 'Second Modal, higher z-index, small size';
|
|
6
|
+
@api options = [];
|
|
7
|
+
|
|
8
|
+
handleOptionClick(e) {
|
|
9
|
+
const { target } = e;
|
|
10
|
+
this.close(parseInt(target.dataset.id, 10));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { LightningElement } from 'lwc';
|
|
2
|
+
|
|
3
|
+
import ModalDemo from 'modal/demo';
|
|
4
|
+
|
|
5
|
+
export default class OverlayBasic extends LightningElement {
|
|
6
|
+
demoResult = 'unset';
|
|
7
|
+
|
|
8
|
+
handleDemoModal() {
|
|
9
|
+
ModalDemo.open({
|
|
10
|
+
// LightningModal
|
|
11
|
+
size: 'large',
|
|
12
|
+
// ModalDemo
|
|
13
|
+
header: 'Select an Option',
|
|
14
|
+
body: 'Select an option:',
|
|
15
|
+
options: [
|
|
16
|
+
{ id: 1, label: 'Option 1' },
|
|
17
|
+
{ id: 2, label: 'Option 2' },
|
|
18
|
+
],
|
|
19
|
+
}).then((result) => {
|
|
20
|
+
if (result === null) {
|
|
21
|
+
this.demoResult = 'dismiss';
|
|
22
|
+
} else {
|
|
23
|
+
this.demoResult = result;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<lightning-modal-header label={header}></lightning-modal-header>
|
|
3
|
+
<lightning-modal-body>
|
|
4
|
+
<p>{body}</p>
|
|
5
|
+
<ul>
|
|
6
|
+
<template for:each={options} for:item="option">
|
|
7
|
+
<li key={option.id}>
|
|
8
|
+
<button onclick={handleOptionClick} data-id={option.id}>
|
|
9
|
+
{option.label}
|
|
10
|
+
</button>
|
|
11
|
+
</li>
|
|
12
|
+
</template>
|
|
13
|
+
</ul>
|
|
14
|
+
</lightning-modal-body>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { api } from 'lwc';
|
|
2
|
+
import LightningModal from 'lightning/modal';
|
|
3
|
+
|
|
4
|
+
export default class ModalDemo extends LightningModal {
|
|
5
|
+
@api header = 'Select an Option';
|
|
6
|
+
@api body = 'Select an option:';
|
|
7
|
+
@api options = [];
|
|
8
|
+
|
|
9
|
+
handleOptionClick(e) {
|
|
10
|
+
const { target } = e;
|
|
11
|
+
this.close(parseInt(target.dataset.id, 10));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<lightning-modal-header label={header}>
|
|
3
|
+
Here’s a tagline if you need it. It is allowed to extend across
|
|
4
|
+
mulitple lines, so I’m making up content to show that to you.
|
|
5
|
+
It is allowed to have links like this <a
|
|
6
|
+
href="https://salesforce.com" target="_blank">Salesforce.com</a>.
|
|
7
|
+
</lightning-modal-header>
|
|
8
|
+
<lightning-modal-body>
|
|
9
|
+
<p>Sit nulla est ex deserunt exercitation anim occaecat. Nostrud ullamco deserunt aute id consequat veniam incididunt duis in sint irure nisi. Mollit officia cillum Lorem ullamco minim nostrud elit officia tempor esse quis. Cillum sunt ad dolore quis
|
|
10
|
+
aute consequat ipsum magna exercitation reprehenderit magna. Tempor cupidatat consequat elit dolor adipisicing.</p>
|
|
11
|
+
<p>Dolor eiusmod sunt ex incididunt cillum quis nostrud velit duis sit officia. Lorem aliqua enim laboris do dolor eiusmod officia. Mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident. Eiusmod et adipisicing culpa deserunt nostrud
|
|
12
|
+
ad veniam nulla aute est. Labore esse esse cupidatat amet velit id elit consequat minim ullamco mollit enim excepteur ea.</p>
|
|
13
|
+
</lightning-modal-body>
|
|
14
|
+
<lightning-modal-footer>
|
|
15
|
+
<template for:each={options} for:item="option">
|
|
16
|
+
<lightning-button
|
|
17
|
+
key={option.id}
|
|
18
|
+
label={option.label}
|
|
19
|
+
class="slds-button"
|
|
20
|
+
variant={option.variant}
|
|
21
|
+
onclick={handleOptionClick}
|
|
22
|
+
data-id={option.id}
|
|
23
|
+
></lightning-button>
|
|
24
|
+
</template>
|
|
25
|
+
</lightning-modal-footer>
|
|
26
|
+
</template>
|