bootstrap-vue
Version:
With more than 85 components, over 45 available plugins, several directives, and 1000+ icons, BootstrapVue provides one of the most comprehensive implementations of the Bootstrap v4 component and grid system available for Vue.js v2.6, complete with extens
451 lines (370 loc) • 15.5 kB
Markdown
# Form Timepicker
> `<b-form-timepicker>` is a BootstrapVue custom time picker input form control, which provides full
> WAI-ARIA compliance and internationalization support.
## Overview
As a form control wrapper component for the [`<b-time>`](/docs/components/time) component, it
provides additional validation state presentation and a compact interface. Native HTML5 time inputs
vary in presentation, accessibility, and in some instances are not supported by all browsers.
`<b-form-timepicker>` provides a consistent and accessible interface across all browser platforms
and devices.
```html
<template>
<div>
<b-form-timepicker v-model="value" locale="en"></b-form-timepicker>
<div class="mt-2">Value: '{{ value }}'</div>
</div>
</template>
<script>
export default {
data() {
return {
value: ''
}
}
}
</script>
<!-- b-form-timepicker.vue -->
```
## `v-model` return value
`<b-form-timepicker>` always returns a string in the format of `'HH:mm:ss'` which is the same format
returned by native browser `<input type="time">` controls. The value will be in the range of
`'00:00:00'` up to `'23:59:59'` (24-hour clock using the `'h23'` hour cycle syntax).
If no time is selected, then `<b-form-timepicker>` returns an empty string (`''`).
## Disabled and readonly states
Setting the `disabled` prop will remove all interactivity of the `<b-form-timepicker>` component.
Setting the `readonly` prop will disable selecting a time, but will keep the component interactive,
allowing for tabbing between spinbuttons. The `v-model` will not be updated in the readonly state.
```html
<template>
<div>
<b-form-group
label="Select time picker interactive state"
v-slot="{ ariaDescribedby }"
>
<b-form-radio-group
v-model="state"
:aria-describedby="ariaDescribedby"
aria-controls="ex-disabled-readonly"
>
<b-form-radio value="disabled">Disabled</b-form-radio>
<b-form-radio value="readonly">Readonly</b-form-radio>
<b-form-radio value="normal">Normal</b-form-radio>
</b-form-radio-group>
</b-form-group>
<b-form-timepicker
id="ex-disabled-readonly"
:disabled="disabled"
:readonly="readonly"
></b-form-timepicker>
</div>
</template>
<script>
export default {
data() {
return {
state: 'disabled'
}
},
computed: {
disabled() {
return this.state === 'disabled'
},
readonly() {
return this.state === 'readonly'
}
}
}
</script>
<!-- b-form-timepicker-disabled-readonly.vue -->
```
## Validation states
`<b-form-timepicker>` supports invalid and valid styling via the boolean `state` prop. Setting
`state` to boolean `false` will style the input as invalid, while setting it to boolean `true` will
style it as valid. Setting state to `null` will not show any validation state styling (the default).
```html
<template>
<div>
<label for="timepicker-invalid">Choose a time (invalid style)</label>
<b-form-timepicker id="datepicker-invalid" :state="false" class="mb-2"></b-form-timepicker>
<label for="timepicker-valid">Choose a time (valid style)</label>
<b-form-timepicker id="datepicker-valid" :state="true"></b-form-timepicker>
</div>
</template>
<!-- b-form-timepicker-validation.vue -->
```
Note that native browser validation is not available with `<b-form-timepicker>`.
## Styling
### Enabling of seconds spinbutton
By default, the seconds spinbutton is not shown. To enable the section of seconds, set the
`show-seconds` prop to `true` to enable the seconds selection spinbutton. When `show-seconds` is
false (or not provided), the returned value will always have the seconds portion of the time string
set to `00`.
```html
<template>
<div>
<b-form-timepicker v-model="value" show-seconds locale="en"></b-form-timepicker>
<div class="mt-2">Value: '{{ value }}'</div>
</div>
</template>
<script>
export default {
data() {
return {
value: ''
}
}
}
</script>
<!-- b-form-timepicker-show-seconds.vue -->
```
### Control sizing
Fancy a smaller or larger `<b-form-timepicker>` control? Set the `size` prop to `'sm'` for a smaller
form control, or `'lg'` for a larger form form control. Note this does not affect the size of the
popup time selection dialog.
```html
<template>
<div>
<label for="timepicker-sm">Small time picker</label>
<b-form-timepicker id="timepicker-sm" size="sm" locale="en" class="mb-2"></b-form-timepicker>
<label for="timepicker-lg">Large time picker</label>
<b-form-timepicker id="timepicker-lg" size="lg" locale="en"></b-form-timepicker>
</div>
</template>
<!-- b-form-timepicker-control-size.vue -->
```
### Placeholder
Add custom placeholder text to the control, when no date is selected, via the `placeholder` prop. If
a placeholder is not provided, the value of the `label-no-time-selected` prop is used.
```html
<template>
<div>
<label for="timepicker-placeholder">Time picker with placeholder</label>
<b-form-timepicker id="timepicker-placeholder" placeholder="Choose a time" locale="en"></b-form-timepicker>
</div>
</template>
<!-- b-form-timepicker-placeholder.vue -->
```
### Optional controls
Add optional control buttons to the bottom of the calendar popup via the props `now-button` or
`reset-button`. The default close button can be removed via the `no-close-button` prop.
- The now button selects the current time
- The reset button either clears the selected time, or sets the time to the value of the prop
`reset-value` (if provided)
- The close button closes the time popup
```html
<template>
<div>
<label for="timepicker-buttons">Time picker with optional footer buttons</label>
<b-form-timepicker
id="timepicker-buttons"
now-button
reset-button
locale="en"
></b-form-timepicker>
</div>
</template>
<!-- b-form-timepicker-footer-buttons.vue -->
```
The text for the optional buttons can be set via the `label-now-button`, `label-reset-button`, and
the `label-close-button` props. Due to the limited width of the footer section, it is recommended to
keep these labels short.
### Dropdown placement
Use the dropdown props `right`, `dropup`, `dropright`, `dropleft`, `no-flip`, and `offset` to
control the positioning of the popup calendar.
Refer to the [`<b-dropdown>` positioning section](/docs/components/dropdown#positioning) for details
on the effects and usage of these props.
### Button only mode
<span class="badge badge-info small">v2.7.0+</span>
Fancy just a button that launches the timepicker dialog, or want to provide your own optional text
input field? Use the `button-only` prop to render the timepicker as a dropdown button. The formatted
time label will be rendered with the class `sr-only` (available only to screen readers).
In the following simple example, we are placing the timepicker (button only mode) as an append to a
`<b-input-group>`:
```html
<template>
<div>
<label for="example-input">Choose a time</label>
<b-input-group class="mb-3">
<b-form-input
id="example-input"
v-model="value"
type="text"
placeholder="HH:mm:ss"
></b-form-input>
<b-input-group-append>
<b-form-timepicker
v-model="value"
button-only
right
show-seconds
locale="en"
aria-controls="example-input"
></b-form-timepicker>
</b-input-group-append>
</b-input-group>
<p>Value: '{{ value }}'</p>
</div>
</template>
<script>
export default {
data() {
return {
value: ''
}
}
}
</script>
<!-- b-form-timepicker-button-only.vue -->
```
Control the size of the button via the `size` prop, and the button variant via the `button-variant`
prop.
## Internationalization
Internationalization of the time interface is provided via
[`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat)
and
[`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat),
except for the labels applied to elements of the time control (aria-labels, selected status, etc.).
You must provide your own translations for these labels. The available locales will be browser
dependent (not all browsers support all locales).
By default `<b-form-timepicker>` will use the browser's default locale, but you can specify the
locale (or locales) to use via the `locale` prop. The prop accepts either a single locale string, or
an array of locale strings (listed in order of most preferred locale to least preferred).
The emitted `'context'` event will include which locale the time control has resolved to (which may
not be the same locale as requested, depending on the supported locales of `Intl`).
For server side rendering (SSR) when using Node.js, ensure that the Node.js runtime you are using
supports `Intl` and the locales you will be using. Refer to the
[Node Intl support documentation](https://nodejs.org/api/intl.html) for details.
```html
<template>
<b-row>
<b-col cols="12" class="mb-3">
<label for="example-locales">Locale:</label>
<b-form-select id="example-locales" v-model="locale" :options="locales"></b-form-select>
</b-col>
<b-col md="6">
<b-form-timepicker
v-model="value"
v-bind="labels[locale] || {}"
:locale="locale"
show-seconds
@context="onContext"
></b-form-timepicker>
</b-col>
<b-col>
<p>Value: <b>'{{ value }}'</b></p>
<p class="mb-0">Context:</p>
<pre class="small">{{ context }}</pre>
</b-col>
</b-row>
</template>
<script>
export default {
data() {
return {
value: '',
context: null,
locale: 'en-US',
locales: [
{ value: 'en-US', text: 'English US (en-US)' },
{ value: 'de', text: 'German (de)' },
{ value: 'ar-EG', text: 'Arabic Egyptian (ar-EG)' },
{ value: 'zh', text: 'Chinese (zh)' }
],
labels: {
de: {
labelHours: 'Stunden',
labelMinutes: 'Minuten',
labelSeconds: 'Sekunden',
labelIncrement: 'Erhöhen',
labelDecrement: 'Verringern',
labelSelected: 'Ausgewählte Zeit',
labelNoTimeSelected: 'Keine Zeit ausgewählt',
labelCloseButton: 'Schließen'
},
'ar-EG': {
labelHours: 'ساعات',
labelMinutes: 'الدقائق',
labelSeconds: 'ثواني',
labelAmpm: 'صباحا مساء',
labelAm: 'ص',
labelPm: 'م',
labelIncrement: 'زيادة',
labelDecrement: 'إنقاص',
labelSelected: 'الوقت المحدد',
labelNoTimeSelected: 'لا وقت المختار',
labelCloseButton: 'قريب'
},
zh: {
labelHours: '小时',
labelMinutes: '分钟',
labelSeconds: '秒',
labelAmpm: '上午下午',
labelAm: '上午',
labelPm: '下午',
labelIncrement: '增量',
labelDecrement: '减量',
labelSelected: '选定时间',
labelNoTimeSelected: '没有选择时间',
labelCloseButton: '关'
}
}
}
},
methods: {
onContext(ctx) {
this.context = ctx
}
}
}
</script>
<!-- b-form-time-i18n.vue -->
```
### Understanding the `hourCycle`
There are 2 main types of time keeping conventions (clocks) used around the world: the 12-hour clock
and the 24-hour clock. The `hourCycle` property allows you to access the clock type used by a
particular locale. The hour cycle type can have several different values, which are listed in the
table below. The `hourCycle` signals how the time `'00:00:00'` (the start of the day) should be
presented/formatted to a user of a particular locale. The `'context'` event includes the resolved
`hourCycle` value.
| `hourCycle` | Description |
| ----------- | --------------------------------------------------------------------------------- |
| `'h12'` | Hour system using `1`–`12`. The 12 hour clock, with midnight starting at 12:00 am |
| `'h23'` | Hour system using `0`–`23`. The 24 hour clock, with midnight starting at 0:00 |
| `'h11'` | Hour system using `0`–`11`. The 12 hour clock, with midnight starting at 0:00 am |
| `'h24'` | Hour system using `1`–`24`. The 24 hour clock, with midnight starting at 24:00 |
Native HTML5 `<input type="date">` returns the time value in the `'h23'` format, and
`<b-form-timepicker>` also returns the v-model in the `'h23'` format. This value may differ from
what is presented to the user via the GUI (spin buttons) of the `<b-form-timepicker>` component,
dependent upon the [locale selected](#internationalization).
**Note:** IE 11 _does not support_ resolving the `hourCycle` value of a locale, so we assume either
`h12` or `h23` based on the resolved `hour12` value.
### Forcing 12 or 24 hour interface
12-hour versus 24-hour input is determined by the client browsers default locale (or the locale
resolved from the `locale` prop). To force a 12-hour user interface, set the prop `hour12` to
`true`. To force a 24-hour user interface, set the prop `hour12` to `false`. The default for prop
`hour12` is `null` which uses the resolved locale to determine which interface to use.
The setting of the `hour12` prop will affect which [`hourCycle`](#understanding-the-hourcycle) is
resolved for formatting the hours spinbutton. Note that while this may affect the format of the hour
spinbutton, but the formatted time string result _may_ show the `'h12` or `'h23'` format due to
limitations in the client `Intl.DateTimeFormat` support for a particular locale. It is therefore
**recommended to leave the `hour12` prop set to `null` (default)**, so show the locale default
time/hour formatting.
## Accessibility
The popup time supports the same keyboard controls as
[`<b-time>`](/docs/components/time#accessibility), along with the following:
- <kbd>Esc</kbd> will close the popup time without selecting a time
When internationalizing the timepicker, it is important to also update the `label-*` props with
appropriate translated strings, so that international screen reader users will hear the correct
prompts and descriptions.
Refer to the [`<b-time>`](/docs/components/time#accessibility) documentation for additional details.
## Implementation notes
`<b-form-timepicker>` is based upon the components [`<b-time>`](/docs/components/time) and
[`<b-dropdown>`](/docs/components/dropdown).
`<b-form-timepicker>` uses Bootstrap's border and flex utility classes, along with button (`btn-*`)
classes, dropdown (`dropdown*`) classes, and the `form-control*` (plus validation) classes.
BootstrapVue's Custom SCSS/CSS is also required for proper styling of the time picker and popup.
## See also
- [`<b-time>` Time selection widget](/docs/components/time)
- [`<b-form-datepicker>` Date picker custom form input](/docs/components/form-datepicker)
- [`<b-calendar>` Calendar date selection widget](/docs/components/calendar)
- [`<b-dropdown>` Dropdown component](/docs/components/dropdown)