1 | # Modals
|
2 |
|
3 | > Modals are streamlined, but flexible dialog prompts powered by JavaScript and CSS. They
|
4 | support a number of use cases from user notification to completely custom content and
|
5 | feature a handful of helpful sub-components, sizes, variants, accessibility, and more.
|
6 |
|
7 | ```html
|
8 | <div>
|
9 | <b-btn v-b-modal.modal1>Launch demo modal</b-btn>
|
10 |
|
11 | <!-- Modal Component -->
|
12 | <b-modal id="modal1" title="Bootstrap-Vue">
|
13 | <p class="my-4">Hello from modal!</p>
|
14 | </b-modal>
|
15 | </div>
|
16 |
|
17 | <!-- modal-1.vue -->
|
18 | ```
|
19 |
|
20 | ## Overview
|
21 | `<b-modal>`, by default, has an **OK** and **Cancel** buttons in the footer. These buttons can
|
22 | be customized by setting various props on the component. You can customize the size of the buttons,
|
23 | disable buttons, hide the **Cancel** button (i.e. OK Only), choose a variant (e.g. `danger`
|
24 | for a red OK button) using the `ok-variant` and `cancel-variant` props, and provide custom
|
25 | button content using the `ok-title` and `cancel-title` props, or using the named
|
26 | slots `modal-ok` and `modal-cancel`.
|
27 |
|
28 | `<b-modal>` supports close on ESC (enabled by default), close on backdrop click (enabled by default), and
|
29 | the `X` close button in the header (enabled by default). These features may be disabled by setting the the
|
30 | props `no-close-on-esc`, `no-close-on-backdrop`, and `hide-header-close` respectively.
|
31 |
|
32 | You can override the modal title via the named slot `modal-title`, override the
|
33 | header completely via the `modal-header` slot, and override the footer completely
|
34 | via the `modal-footer` slot.
|
35 |
|
36 | **Note**: when using the `modal-footer` slot, the default **OK** and **Cancel** buttons will not
|
37 | be present. Also, if you use the `modal-header` slot, the default header `X` close button will
|
38 | not be present, nor can you use the `modal-title` slot.
|
39 |
|
40 | ## Toggle Modal Visibility
|
41 |
|
42 | There are several methods that you can employ to toggle the visibility of `<b-modal>`.
|
43 |
|
44 | ### Using `v-b-modal` directive (recommended)
|
45 |
|
46 | Other elements can easily show modals using the `v-b-modal` directive.
|
47 |
|
48 | ```html
|
49 | <div>
|
50 | <!-- Using modifiers -->
|
51 | <b-btn v-b-modal.myModal>Show Modal</b-btn>
|
52 |
|
53 | <!-- Using value -->
|
54 | <b-btn v-b-modal="'myModal'">Show Modal</b-btn>
|
55 |
|
56 | <!-- the modal -->
|
57 | <b-modal id="myModal">
|
58 | Hello From My Modal!
|
59 | </b-modal>
|
60 | </div>
|
61 |
|
62 | <!-- modal-directive-1.vue -->
|
63 | ```
|
64 |
|
65 | Focus will automatically be returned to the trigger element once the modal closes.
|
66 | See the **Accessibility** section below for details.
|
67 |
|
68 | ### Using `show()` and `hide()` component methods
|
69 |
|
70 | You can access modal using `ref` attribute and then call the `show()` or `hide()` methods.
|
71 |
|
72 | ```html
|
73 | <template>
|
74 | <div>
|
75 | <b-button @click="showModal">
|
76 | Open Modal
|
77 | </b-button>
|
78 | <b-modal ref="myModalRef" hide-footer title="Using Component Methods">
|
79 | <div class="d-block text-center">
|
80 | <h3>Hello From My Modal!</h3>
|
81 | </div>
|
82 | <b-btn class="mt-3" variant="outline-danger" block @click="hideModal">Close Me</b-btn>
|
83 | </b-modal>
|
84 | </div>
|
85 | </template>
|
86 |
|
87 | <script>
|
88 | export default {
|
89 | methods: {
|
90 | showModal () {
|
91 | this.$refs.myModalRef.show()
|
92 | },
|
93 | hideModal () {
|
94 | this.$refs.myModalRef.hide()
|
95 | }
|
96 | }
|
97 | }
|
98 | </script>
|
99 |
|
100 | <!-- modal-methods-1.vue -->
|
101 | ```
|
102 |
|
103 | The `hide()` method accepts an optional argument. See section **Prevent Closing**
|
104 | below for details.
|
105 |
|
106 | ### Using `v-model` property
|
107 |
|
108 | `v-model` property is always automatically synced with `<b-modal>` visible state
|
109 | and you can show/hide using `v-model`.
|
110 |
|
111 | ```html
|
112 | <template>
|
113 | <div>
|
114 | <b-button @click="modalShow = !modalShow">
|
115 | Open Modal
|
116 | </b-button>
|
117 | <b-modal v-model="modalShow">
|
118 | Hello From Modal!
|
119 | </b-modal>
|
120 | </div>
|
121 | </template>
|
122 |
|
123 | <script>
|
124 | export default {
|
125 | data () {
|
126 | return {
|
127 | modalShow: false
|
128 | }
|
129 | }
|
130 | }
|
131 | </script>
|
132 |
|
133 | <!-- modal-v-model-1.vue -->
|
134 | ```
|
135 |
|
136 | When using the `v-model` property, do not use the `visible` property at the same time.
|
137 |
|
138 |
|
139 | ### Emitting Events on $root
|
140 |
|
141 | You can emit `bv::show::modal` and `bv::hide::modal` event on `$root` with the first
|
142 | argument set to the modal's id. An optional second argument can specify the element
|
143 | to return focus to once the modal is closed. The second argument can be a CSS selector,
|
144 | an element reference, or a component reference.
|
145 |
|
146 | ```html
|
147 | <div>
|
148 | <b-button @click="showModal" ref="btnShow">
|
149 | Open Modal
|
150 | </b-button>
|
151 | <b-modal @hidden="onHidden">
|
152 | <div class="d-block">Hello From My Modal!</div>
|
153 | <b-btn @click="hideModal">Close Me</b-btn>
|
154 | </b-modal>
|
155 | </div>
|
156 | ```
|
157 |
|
158 | ```js
|
159 | methods: {
|
160 | showModal () {
|
161 | this.$root.$emit('bv::show::modal','modal1')
|
162 | },
|
163 | hideModal () {
|
164 | this.$root.$emit('bv::hide::modal','modal1')
|
165 | },
|
166 | onHidden (evt) {
|
167 | // Return focus to our Open Modal button
|
168 | // See accessibility below for additional return-focus methods
|
169 | this.$refs.btnShow.$el.focus()
|
170 | }
|
171 | }
|
172 | ```
|
173 |
|
174 |
|
175 | ## Prevent Closing
|
176 |
|
177 | To prevent `<b-modal>` from closing (for example when validation fails). you can call
|
178 | the `preventDefault()` method of the event object passed to your `ok` (**OK** button),
|
179 | `cancel` (**Cancel** button) and `hide` event handlers.
|
180 |
|
181 | ```html
|
182 | <template>
|
183 | <div>
|
184 | <b-btn v-b-modal.modalPrevent>Launch demo modal</b-btn>
|
185 | <!-- Main UI -->
|
186 | <div class="mt-3 mb-3">
|
187 | Submitted Names:
|
188 | <ul>
|
189 | <li v-for="n in names">{{n}}</li>
|
190 | </ul>
|
191 | </div>
|
192 | <!-- Modal Component -->
|
193 | <b-modal id="modalPrevent"
|
194 | ref="modal"
|
195 | title="Submit your name"
|
196 | @ok="handleOk"
|
197 | @shown="clearName">
|
198 | <form @submit.stop.prevent="handleSubmit">
|
199 | <b-form-input type="text"
|
200 | placeholder="Enter your name"
|
201 | v-model="name"></b-form-input>
|
202 | </form>
|
203 | </b-modal>
|
204 | </div>
|
205 | </template>
|
206 |
|
207 | <script>
|
208 | export default {
|
209 | data () {
|
210 | return {
|
211 | name: '',
|
212 | names: []
|
213 | }
|
214 | },
|
215 | methods: {
|
216 | clearName () {
|
217 | this.name = ''
|
218 | },
|
219 | handleOk (evt) {
|
220 | // Prevent modal from closing
|
221 | evt.preventDefault()
|
222 | if (!this.name) {
|
223 | alert('Please enter your name')
|
224 | } else {
|
225 | this.handleSubmit()
|
226 | }
|
227 | },
|
228 | handleSubmit () {
|
229 | this.names.push(this.name)
|
230 | this.clearName()
|
231 | this.$refs.modal.hide()
|
232 | }
|
233 | }
|
234 | }
|
235 | </script>
|
236 |
|
237 | <!-- modal-prevent-1.vue -->
|
238 | ```
|
239 |
|
240 | **Note**: events `ok` and `cancel` are emitted by modal's built in **OK** and **Cancel**
|
241 | buttons respectively. These events will not be emitted, by default, if you have provided your own
|
242 | buttons in the `modal-footer` slot or have hidden the footer. In this case use the `hide` event
|
243 | to control cancelling of the modal close. Event `hide` is always emitted, even if `ok` and `cancel`
|
244 | are emitted.
|
245 |
|
246 | The `ok`, `cancel`, and `hide` event object contains several properties and methods:
|
247 |
|
248 | | Property or Method | Type | Description
|
249 | | ------------ | ------ | --------------------------------------------
|
250 | | `e.preventDefault()` | Method | When called prevents the modal from closing
|
251 | | `trigger` | Property | Will be one of: `ok` (Default **OK** Clicked), `cancel` (Default **Cancel** clicked), `esc` (if the <kbd>ESC</kbd> key was pressed), `backdrop` (if the backdrop was clicked), `headerclose` (if the header X button was clicked), the argument provided to the `hide()` method, or `undefined` otherwise.
|
252 | | `target` | Property | A reference to the modal element
|
253 | | `vueTarget` | property | A reference to the modal's Vue VM instance
|
254 |
|
255 | You can set the value of `trigger` by passing an argument to the component's
|
256 | `hide()` method for advanced control.
|
257 |
|
258 | **Note:** `ok` and `cancel` events will be only emitted when the argument to `hide()` is strictly `'ok'`
|
259 | or `'cancel'` respectively. The argument passed to `hide()` will be placed into the
|
260 | `trigger` property of the event object.
|
261 |
|
262 |
|
263 | ## Modal sizing
|
264 | Modals have two optional sizes, available via the prop `size`. These sizes kick in at certain
|
265 | breakpoints to avoid horizontal scrollbars on narrower viewports. Valid optional sizes are
|
266 | `lg`, or `sm`.
|
267 |
|
268 | ```html
|
269 | <div>
|
270 | <b-btn v-b-modal.modallg variant="primary">Large modal</b-btn>
|
271 | <b-btn v-b-modal.modalsm variant="primary">Small modal</b-btn>
|
272 |
|
273 | <b-modal id="modallg" size="lg" title="Large Modal">
|
274 | Hello Modal!
|
275 | </b-modal>
|
276 | <b-modal id="modalsm" size="sm" title="Small Modal">
|
277 | Hello Modal!
|
278 | </b-modal>
|
279 | </div>
|
280 |
|
281 | <!-- modal-sizes.vue -->
|
282 | ```
|
283 |
|
284 |
|
285 | ## Vertically centering
|
286 | Vertically center your modal in the viewport by setting the `centered` prop.
|
287 |
|
288 | ```html
|
289 | <div>
|
290 | <b-btn v-b-modal.modal-center>Launch centered modal</b-btn>
|
291 |
|
292 | <!-- Modal Component -->
|
293 | <b-modal id="modal-center" centered title="Bootstrap-Vue">
|
294 | <p class="my-4">Vertically centered modal!</p>
|
295 | </b-modal>
|
296 | </div>
|
297 |
|
298 | <!-- modal-center-v.vue -->
|
299 | ```
|
300 |
|
301 | ## Using the grid
|
302 | Utilize the Bootstrap grid system within a modal by nesting `<b-container fluid>` within
|
303 | the modal-body. Then, use the normal grid system `<b-row>` (or `<b-form-row>`) and `<b-col>`
|
304 | as you would anywhere else.
|
305 |
|
306 |
|
307 | ## Tooltips and popovers
|
308 | Tooltips and popovers can be placed within modals as needed. When modals are closed, any tooltips
|
309 | and popovers within are also automatically dismissed. Tooltips and popovers are automatically
|
310 | appended to the modal element (to ensure correct z-indexing), although you can override where
|
311 | they are appended by specifying a container ID (refer to tooltip and popover docs for details).
|
312 |
|
313 | ```html
|
314 | <div>
|
315 | <b-btn v-b-modal.modalPopover>Show Modal</b-btn>
|
316 | <b-modal id="modalPopover" title="Modal with Popover" ok-only>
|
317 | <p>
|
318 | This
|
319 | <b-btn v-b-popover="'Popover inside a modal!'" title="Popover">
|
320 | Button
|
321 | </b-btn>
|
322 | triggers a popover on click.
|
323 | </p>
|
324 | <p>
|
325 | This <a href="#" v-b-tooltip title="Tooltip in a modal!">Link</a>
|
326 | will show a tooltip on hover.
|
327 | </p>
|
328 | </b-modal>
|
329 | </div>
|
330 |
|
331 | <!-- modal-popover.vue -->
|
332 | ```
|
333 |
|
334 |
|
335 | ## Variants
|
336 | Control the header, footer, and body background and text variants by setting the
|
337 | `header-bg-variant`, `header-text-variant`, `body-bg-variant`, `body-text-variant`,
|
338 | `footer-bg-variant`, and `footer-text-variant` props. Use any of the standard Bootstrap
|
339 | variants such as `danger`, `warning`, `info`, `success`, `dark`, `light`, etc.
|
340 |
|
341 | The variants for the bottom border of the header and top border of the footer can be
|
342 | controlled by the `header-border-variant` and `footer-border-variant` props respectively.
|
343 |
|
344 | ```html
|
345 | <template>
|
346 | <div>
|
347 | <b-btn @click="show=true" variant="primary">Show Modal</b-btn>
|
348 | <b-modal v-model="show"
|
349 | title="Modal Variants"
|
350 | :header-bg-variant="headerBgVariant"
|
351 | :header-text-variant="headerTextVariant"
|
352 | :body-bg-variant="bodyBgVariant"
|
353 | :body-text-variant="bodyTextVariant"
|
354 | :footer-bg-variant="footerBgVariant"
|
355 | :footer-text-variant="footerTextVariant">
|
356 | <b-container fluid>
|
357 | <b-row class="mb-1 text-center">
|
358 | <b-col cols="3"> </b-col>
|
359 | <b-col>Background</b-col>
|
360 | <b-col>Text</b-col>
|
361 | </b-row>
|
362 | <b-row class="mb-1">
|
363 | <b-col cols="3">Header</b-col>
|
364 | <b-col><b-form-select :options="variants" v-model="headerBgVariant" /></b-col>
|
365 | <b-col><b-form-select :options="variants" v-model="headerTextVariant" /></b-col>
|
366 | </b-row>
|
367 | <b-row class="mb-1">
|
368 | <b-col cols="3">Body</b-col>
|
369 | <b-col><b-form-select :options="variants" v-model="bodyBgVariant" /></b-col>
|
370 | <b-col><b-form-select :options="variants" v-model="bodyTextVariant" /></b-col>
|
371 | </b-row>
|
372 | <b-row>
|
373 | <b-col cols="3">Footer</b-col>
|
374 | <b-col><b-form-select :options="variants" v-model="footerBgVariant" /></b-col>
|
375 | <b-col><b-form-select :options="variants" v-model="footerTextVariant" /></b-col>
|
376 | </b-row>
|
377 | </b-container>
|
378 | <div slot="modal-footer" class="w-100">
|
379 | <p class="float-left">Modal Footer Content</p>
|
380 | <b-btn size="sm" class="float-right" variant="primary" @click="show=false">
|
381 | Close
|
382 | </b-btn>
|
383 | </div>
|
384 | </b-modal>
|
385 | </div>
|
386 | </template>
|
387 |
|
388 | <script>
|
389 | export default {
|
390 | data () {
|
391 | return {
|
392 | show: false,
|
393 | variants: [
|
394 | 'primary', 'secondary', 'success', 'warning', 'danger', 'info', 'light', 'dark'
|
395 | ],
|
396 | headerBgVariant: 'dark',
|
397 | headerTextVariant: 'light',
|
398 | bodyBgVariant: 'light',
|
399 | bodyTextVariant: 'dark',
|
400 | footerBgVariant: 'warning',
|
401 | footerTextVariant: 'dark'
|
402 | }
|
403 | }
|
404 | }
|
405 | </script>
|
406 |
|
407 | <!-- modal-variant-1.vue -->
|
408 | ```
|
409 |
|
410 |
|
411 | ## Lazy loading
|
412 | Modal will always render its HTML markup in the document at the location that
|
413 | the `<b-modal>` component is placed (even if it is not shown). You can hide
|
414 | the modal markup from being in the DOM while modal is in the hidden state by
|
415 | setting the `lazy` prop.
|
416 |
|
417 |
|
418 | ## Disable open and close animation
|
419 | To disable the fading transition/animation when modal opens and closes, just set the prop
|
420 | `no-fade` on the `<b-modal>` component.
|
421 |
|
422 |
|
423 | ## Disabling built-in buttons
|
424 | You can disable the built-in footer buttons programatically.
|
425 |
|
426 | You can disable the **Cancel** and **OK** buttons individually by setting the `cancel-disabled`
|
427 | and `ok-disabled` props, respectively, to `true`. Set the prop to `false` to re-enable
|
428 | the button.
|
429 |
|
430 | To disable both **Cancel** and **OK** buttons at teh same time, simply set the `busy`
|
431 | prop to `true`. Set it to `false` to re-enable both buttons.
|
432 |
|
433 |
|
434 | ## Accessibility
|
435 |
|
436 | `<b-modal>` provides several accessibility features, including auto focus, return
|
437 | focus, and keyboard (tab) _focus containment_.
|
438 |
|
439 | For `aria-labelledby` and `aria-described` by attributes to appear on the
|
440 | modal, you **must** supply an `id` attribute on `<b-modal>`. `aria-labelledby` will
|
441 | not be present if you have the header hidden.
|
442 |
|
443 | ## Auto Focus on open
|
444 |
|
445 | `<b-modal>` will autofocus the modal container when opened.
|
446 |
|
447 | You can pre-focus an element within the `<b-modal>` by listening to the `<b-modal>` `shown` event, and
|
448 | call the element's `focus()` method. `<b-modal>` will not attempt to autofocus if
|
449 | an element already has focus within the `<b-modal>`.
|
450 |
|
451 | ```html
|
452 | <b-modal @shown="focusMyElement">
|
453 | <b-button>I Don't Have Focus</b-button>
|
454 | <br>
|
455 | <b-form-input type="text"></b-form-input>
|
456 | <br>
|
457 | <!-- element to gain focus when modal is opened -->
|
458 | <b-form-input ref="focusThis" type="text"></b-form-input>
|
459 | <br>
|
460 | <b-form-input type="text"></b-form-input>
|
461 | </b-modal>
|
462 | ```
|
463 |
|
464 | ```js
|
465 | methods: {
|
466 | focusMyElement (e) {
|
467 | this.$refs.focusThis.focus()
|
468 | }
|
469 | }
|
470 | ```
|
471 |
|
472 | ## Returning focus to the triggering element
|
473 |
|
474 | For accessibility reasons, it is desirable to return focus to the element
|
475 | that triggered the opening of the modal, when the modal closes. `<b-modal>`
|
476 | provides several methods and options for returning focus to the triggering element.
|
477 |
|
478 | ### Specify Return Focus Element via the `return-focus` Prop
|
479 |
|
480 | You can also specify an element to return focus to, when modal closes, by setting
|
481 | the `return-focus` prop to one of the following:
|
482 |
|
483 | - A CSS Query Selector string (or an element ID prepended with `#`)
|
484 | - A component reference (which is mounted on a focusable element, such as `<b-button>`)
|
485 | - A reference to a DOM element that is focusable
|
486 |
|
487 | If the passed in element is not focusable, then the browser will determine
|
488 | what has focus (usually `<body>`, which is not desireable)
|
489 |
|
490 | This method for returning focus is handy when you use the `<b-modal>` methods `show()`
|
491 | and `hide()`, or the `v-model` prop. Note this property takes
|
492 | precedence over other methods of specifying the return focus element.
|
493 |
|
494 | ### Auto Return Focus
|
495 |
|
496 | When `<b-modal>` is opened via the `v-b-modal` directive on an element, focus will be
|
497 | returned to this element automatically when `<b-modal>` closes, unless an element has
|
498 | been specified via the `return-focus` prop.
|
499 |
|
500 | ### Specify Return Focus via Event
|
501 |
|
502 | When using the `bv::show::modal` event (emitted on `$root`), you can specify a second argument
|
503 | which is the element to return focus to. This argument accepts the same types
|
504 | as the `return-focus` prop.
|
505 |
|
506 | ```js
|
507 | this.$root.$emit('bv::show::modal', 'modal1', '#focusThisOnClose');
|
508 | ```
|
509 |
|
510 | *Tip:* if using a click event (or similar) to trigger modal to open, pass the
|
511 | event's `target` property:
|
512 |
|
513 | ```html
|
514 | <b-btn @click="$root.$emit.('bv::show::modal', 'modal1', $event.target)">
|
515 | Open Modal
|
516 | </b-btn>
|
517 | ```
|
518 |
|
519 | **Note:** If the `<b-modal>` has the `return-focus` prop set, then the element specified
|
520 | via the event will be ignored.
|
521 |
|
522 |
|
523 | ## Keyboard Navigation
|
524 |
|
525 | When tabbing through elements within a `<b-modal>`, if focus attempts to leave the modal into the document,
|
526 | it will be brought back into the modal.
|
527 |
|
528 | In some circumstances, you may need to disable the enforce focus feature. You can do this
|
529 | by setting the prop `no-enforce-focus`.
|
530 |
|
531 |
|
532 | ## Component Reference
|