Vue2 Timepicker
💡 Dead repo recharged 🔋
A dropdown time picker (hour|minute|second) for Vue 2.x, with flexible time format support.
Demo
You can see the Vue2 Timepicker in action in the Demo Page
Migration
Please check MIGRATION.md for basic guidelines if you are about to:
- Migrate from the Vue 1.x version vue-time-picker
- Migrate from Bower to Yarn or NPM (Vue2 Timepicker
v0.1.x
-> v0.2.0+
)
Dependencies
Vue.js
Installation
yarn add vue2-timepicker
npm install vue2-timepicker --save
NOTE: We stop Bower support from 0.2.0+
, please check MIGRATION.md for migration guidelines.
Get Started
Step 1: Import VueTimepicker
Option A: Import component JS and CSS
import VueTimepicker from 'vue2-timepicker'
import 'vue2-timepicker/dist/VueTimepicker.css'
Option B: Choose any bundle version base on your needs
Javascript
import VueTimepicker from 'vue2-timepicker/dist/VueTimepicker.common.js'
import VueTimepicker from 'vue2-timepicker/dist/VueTimepicker.umd.js'
import VueTimepicker from 'vue2-timepicker/dist/VueTimepicker.umd.min.js'
CSS
@import 'vue2-timepicker/dist/VueTimepicker.css';
@import '~vue2-timepicker/dist/VueTimepicker.css';
Single File Component
import VueTimepicker from 'vue2-timepicker/src/vue-timepicker.vue'
SSR Usage
import VueTimepicker from 'vue2-timepicker/sfc'
If your server-side renderer cannot recognize the /sfc
alias, please try --
import VueTimepicker from 'vue2-timepicker/src'
import VueTimepicker from 'vue2-timepicker/src/vue-timepicker.vue'
Step 2: Include VueTimepicker in your component
var yourComponent = new Vue({
components: { VueTimepicker },
...
})
Step 3: Put vue-timepicker
in your component's template
Then, you can introduce the vue-timepicker
tag anywhere you like in your component's template
<vue-timepicker></vue-timepicker>
Basic Usage
Base
<vue-timepicker></vue-timepicker>
Customized Time Format
<vue-timepicker format="HH:mm:ss"></vue-timepicker>
<vue-timepicker format="hh:mm A"></vue-timepicker>
<vue-timepicker format="hh:mm:ss a"></vue-timepicker>
VueTimepicker recognizes the following tokens in the format string
Section | Token | Output |
---|
AM/PM | A | AM PM |
| a | am pm |
Hour | H | 0 1 ... 22 23 |
| HH | 00 01 ... 22 23 |
| h | 1 2 ... 11 12 |
| hh | 01 02 ... 11 12 |
| k | 1 2 ... 23 24 |
| kk | 01 02 ... 23 24 |
Minute | m | 0 1 ... 58 59 |
| mm | 00 01 ... 58 59 |
Second | s | 0 1 ... 58 59 |
| ss | 00 01 ... 58 59 |
If not set, the format
string is default to "HH:mm"
Customized Picker Interval
<vue-timepicker :minute-interval="5"></vue-timepicker>
<vue-timepicker :second-interval="10"></vue-timepicker>
<vue-timepicker :minute-interval="yourMinuteInterval"></vue-timepicker>
Data Binding
Bind Value with v-model
From v1.0.0+
, timepicker's v-model
accepts value in both Object (default) and String format. The v0.x
versions only support Object form.
Set Initial Value
For example, if you want to set "10:05:00" ("HH:mm:ss" format) as the initial value of vue-timepicker:
const yourComponent = new Vue({
components: { VueTimepicker },
data () {
return {
yourTimeValue: {
HH: '10',
mm: '05',
ss: '00'
},
yourStringTimeValue: '10:05:00',
...
}
},
...
})
Both forms lead to the same result.
<vue-timepicker v-model="yourTimeValue" format="HH:mm:ss"></vue-timepicker>
<vue-timepicker v-model="yourStringTimeValue" format="HH:mm:ss"></vue-timepicker>
Set Empty Initial Value
When the initial value is completely unknown:
data () {
return {
yourEmptyValue: {},
emptyValueToo: undefined,
emptyValueAsWell: null,
yourEmptyStringValue: ''
}
}
Set Partially-Known Initial Value
For instance, if you want to set the initial hour value to 8 pm and leave the rest slots empty:
data () {
return {
timeValue: {
HH: '20',
mm: ''
},
timeValueWithSec: {
h: '8',
mm: '',
ss: '',
A: 'PM'
},
stringTimeValue: '20:mm',
stringTimeValueWithSec: '8:mm:ss PM'
}
}
<vue-timepicker v-model="timeValue"></vue-timepicker>
<vue-timepicker v-model="timeValueWithSec" format="h:mm:ss A"></vue-timepicker>
<vue-timepicker v-model="stringTimeValue"></vue-timepicker>
<vue-timepicker v-model="stringTimeValueWithSec" format="h:mm:ss A"></vue-timepicker>
Get Time Picker's Current Value
Get value from v-model
You can either read the binding v-model
value anytime or add a handler to deal with the input
event from vue-timepicker.
<vue-timepicker v-model="yourTimeValue" format="HH:mm:ss" @input="inputHandler"></vue-timepicker>
{
data () {
return {
yourTimeValue: {
HH: '10',
mm: '05',
ss: '00'
},
...
}
},
methods: {
inputHandler (eventData) {
console.log(eventData)
}
}
}
In this case, we set the initial value (yourTimeValue) to "10:05:00". Then, open the dropdown picker and pick a new time, like setting it to "14:30:15" for example.
Read Data From change
Event
<vue-timepicker v-model="yourTimeValue" @change="changeHandler"></vue-timepicker>
<vue-timepicker v-model="yourTimeValue" @change="otherChangeHandler($event, 'foo', 42)"></vue-timepicker>
changeHandler (eventData) {
console.log(eventData)
}
otherChangeHandler (eventData, yourArg1, yourArg2) {
console.log(eventData)
console.log(yourArg1)
console.log(yourArg2)
}
Unlike v-model
and input
event, which only return the defined time tokens you provided in the binding variable, the change
event delivers all supported formats.
In the example above, after the user set values to "14:30:15" in the picker, change
event returns the following data:
{
data: {
HH: "14",
H: "14",
hh: "14",
a: "am",
A: "AM",
h: "14",
kk: "14",
k: "14",
m: "30",
mm: "30",
s: "15",
ss: "15"
},
displayTime: "14:30:15"
}
Whereas the v-model
/ input
only return the data with defined tokens
{
HH: "14",
mm: "30",
ss: "15"
}
Advance Usage
Hide Clear Button
<vue-timepicker hide-clear-button></vue-timepicker>
Enable to hide the "×" clear button on the right-hand side. Users can still pick new values from the dropdown, but they cannot erase any selected data.
Disable Picker
<vue-timepicker disabled></vue-timepicker>
Fully disable both dropdown picker and the "×" clear button in the UI, to prevent users from changing any values again.
Close on Complete
Automatically close the dropdown when the user finishes selecting all of the required fields.
<vue-timepicker close-on-complete></vue-timepicker>
Auto-Scroll
<vue-timepicker auto-scroll></vue-timepicker>
Auto-scroll to selected values on dropdown open. It works with both:
- Programmatically defined value. E.g., the initial value from
v-model
- Values manually picked by the user.
Define Hour Range
Sometimes you may want to limit hours picker to a specific range. The hour-range
parameter is here to help.
<vue-timepicker :hour-range="[5, [8, 12], [14, 17], 19]"></vue-timepicker>
<vue-timepicker :hour-range="['7a', '9a', '11a', '1p', ['3p', '5p'], '7p']" format="hh:mm a">
Set Minute and Second Range
Similar to hour-range
, you can determine values in the minutes and seconds dropdown by using minute-range
and second-range
.
<vue-timepicker :minute-range="[0, 6, [10, 30], 42, 50]"></vue-timepicker>
<vue-timepicker format="H:m:s" :second-range="[0, 6, [10, 30], 42, 50]"></vue-timepicker>
When implemented together with minute-interval
and second-interval
, the customized intervals take the priority.
<vue-timepicker :minute-range="[0, 6, [10, 30], 42, 50]" :minute-interval="5"></vue-timepicker>
<vue-timepicker format="H:m:s" :second-range="[0, 6, [10, 30], 42, 50]" :second-interval="10"></vue-timepicker>
Hide Disabled Items
There're four kinds of helper properties to let you hide the values excluded by hour-range
, minute-range
, and second-range
.
- hide-disabled-items: Hide all disabled items - hour, minute, and seconds.
- hide-disabled-hours: Hide disabled hour values only.
- hide-disabled-minutes: Hide disabled minute values only.
- hide-disabled-seconds: Hide disabled second values only.
<vue-timepicker :hour-range="[5, [8, 12], [14, 17], 19]" hide-disabled-hours></vue-timepicker>
Here we take the hide-disabled-hours
as an example. It's a pair with the hour-range
parameter. In this case, the hour picker hides the invalid hours (0, 1, 2, 3, 4, 6, 7, 13, 18, 20, 21, 22, 23) and display the valid hours (5, 8, 9, ...) only.
Advanced Keyboard Support
Basic keyboard support includes:
- Tab: Focus or blur the Timepicker
- Esc: Close the dropdown
Advance Keyboard support (enabled with advanced-keyboard
):
- Arrow Keys: Navigate between valid (non-disabled) values and columns
- Space or Enter: Select the focusing item
<vue-timepicker advanced-keyboard></vue-timepicker>
Please be aware that after putting the advanced-keyboard
on, hundreds of additional keyboard event listeners are going to be attached to the component. The amount of listeners depends on how many hours, minutes, and seconds value you enabled in the current Timepicker.
Blur Delay
<vue-timepicker :blur-delay="500"></vue-timepicker>
Sets the blur delay time for the dropdown. Defaults to 300
if not set.
Manual Input Support
<vue-timepicker manual-input></vue-timepicker>
Let users add or change values through the <input>
box besides the dropdown picker.
Manual Input Timeout
<vue-timepicker :manual-input-timeout="1500"></vue-timepicker>
Works with manual-input mode. It sets the timeout for continuous input. Defaults to 1000
if not set.
How It Works?
For example, when a user focuses on the hour slot (HH
) of a "HH:mm"
formatted Timepicker (with the default value 1000
):
- Case 1: User first inputs
1
, and then inputs 2
500ms later -> Timepicker takes 12
as the final value and set it to the "HH"
slot. - Case 2: User inputs
1
, and then presses the key 2
1200ms later -> Timepicker takes 2
as the final value and set it to 02
for the "HH"
slot.
Hide Dropdown
NOTE: To use this feature, you MUST ENABLE the manual-input
mode (v.1.1.0+) in the first place.
It makes the dropdown picker hidden by default.
<vue-timepicker manual-input hide-dropdown></vue-timepicker>
Users can still choose to open the dropdown by clicking the triangle ("▾") button on the right. (v.1.1.3+)
Fixed Dropdown Button
<vue-timepicker fixed-dropdown-button></vue-timepicker>
Make the dropdown button always visible in the UI. (v.1.1.4+)
Drop Direction
Change dropdown direction when needed (v.1.1.5+). Accepting values:
- down: Default value.
- up: Force open the dropdown above the input.
- auto: Auto detects available height and opens the dropdown on top if there are not enough spaces below the input.
<vue-timepicker drop-direction="up"></vue-timepicker>
<vue-timepicker drop-direction="auto"></vue-timepicker>
Container ID
Works with drop-direction="auto"
. It defines the parent container where the timepicker should calculate the free spaces from. If this value is not set, timepicker will watch document.body
instead.
<div id="auto-dropdown-containter">
<vue-timepicker drop-direction="auto" container-id="auto-dropdown-containter"></vue-timepicker>
<vue-timepicker drop-direction="auto"></vue-timepicker>
</div>
Drop Offset Height
Works with drop-direction="auto"
either. Defaults to 160
(unit: px) if the value is not set.
<vue-timepicker drop-direction="auto" :drop-offset-height="200"></vue-timepicker>
Lazy Event Mode
<vue-timepicker lazy></vue-timepicker>
When lazy
event mode is toggled on, only an actual user behavior can trigger the input
and change
events. Which are:
- The user opened the dropdown and picked a new value
- The user clicked the ("×") clear button
- The user inputted a new value or clear the existing value in the Manual Input mode
In other words, on lazy
mode, Timepicker won't emit input
and change
events on mounted, nor after the value got modified programmatically.
Append To Body
Append the dropdown menu to the end of the document <body>
. Try this if you have z-index
or overflow
layout issue with the dropdown.
<vue-timepicker append-to-body></vue-timepicker>
The body-appended dropdown's CSS class is vue__time-picker-dropdown
. Its default z-index
is 100
. You can change the value by adding the following style in your app --
.vue__time-picker-dropdown {
z-index: 5000;
}
NOTE: If you have to override some of the CSS styles within the dropdown, you will need to update their selectors' class names as well. Simply change any .vue__time-picker .dropdown
selector to .vue__time-picker-dropdown
.
For example, when you have a customized background color set for selected values:
.vue__time-picker .dropdown ul li:not([disabled]).active {
background: steelblue;
}
.vue__time-picker-dropdown ul li:not([disabled]).active {
background: steelblue;
}
Enable Debug Mode
<vue-timepicker debug-mode></vue-timepicker>
It's aimed to help developers to investigate the input -> output process. When debug mode is toggled on, you can see extra DEBUG: ...
logs coming through the console window as you interact with the vue-timepicker.
Let's create a "bug" here as an example --
<vue-timepicker v-model="yourStringValue" format="h:mm:ss A" debug-mode></vue-timepicker>
{
data () {
return {
yourStringValue: 'e:mm:05 A'
}
}
}
Then, in the console window, you should see a debug log saying:
DEBUG: The input string in "v-model" does NOT match the "format" pattern
format: h:mm:ss A
v-model: e:mm:05 A
Main Props API Overview
Prop | Type | Required | Default Value |
---|
v-model | Object, String | no | undefined |
format | String | no | "HH:mm" |
minute-interval | Number | no | undefined |
second-interval | Number | no | undefined |
hide-clear-button | Boolean | no | false |
disabled | Boolean | no | false |
close-on-complete | Boolean | no | false |
auto-scroll | Boolean | no | false |
hour-range | Array | no | undefined |
minute-range | Array | no | undefined |
second-range | Array | no | undefined |
hide-disabled-hours | Boolean | no | false |
hide-disabled-minutes | Boolean | no | false |
hide-disabled-seconds | Boolean | no | false |
hide-disabled-items | Boolean | no | false |
advanced-keyboard | Boolean | no | false |
blur-delay | Number | no | 300 |
manual-input | Boolean | no | false |
manual-input-timeout | Number | no | 1000 |
hide-dropdown | Boolean | no | false |
fixed-dropdown-button | Boolean | no | false |
drop-direction | String | no | "down" |
container-id | String | no | undefined |
drop-offset-height | Number | no | 160 |
lazy | Boolean | no | false |
append-to-body | Boolean | no | false |
debug-mode | Boolean | no | false |
Input Props API
Prop | Type | Required | Default Value |
---|
id | String | no | undefined |
name | String | no | undefined |
placeholder | String | no | undefined |
tabindex | Number | no | 0 |
autocomplete | String | no | 'off' |
input-class | String, Array, Object | no | undefined |
input-width | String | no | '10em' |
Timepicker supports id
, name
, placeholder
, and tabindex
like common form elements. These values are assigned to the <input type="text" class="display-time">
within the component.
Input id
, name
and tabindex
<vue-timepicker id="myFirstPicker"></vue-timepicker>
<vue-timepicker name="nameInForm"></vue-timepicker>
<vue-timepicker :tabindex="5"></vue-timepicker>
Input placeholder
When placeholder
is undefined, timepicker takes the determined format string instead.
<vue-timepicker placeholder="Start Time"></vue-timepicker>
<vue-timepicker format="hh:mm A"></vue-timepicker>
<vue-timepicker></vue-timepicker>
Input autocomplete
Attribute
NOTE: To use this property, you MUST ENABLE the manual-input
mode (v.1.1.0+) in the first place.
<vue-timepicker name="starttime" autocomplete="on" manual-input></vue-timepicker>
<span class="vue__time-picker time-picker">
<input class="display-time" name="starttime" type="text" autocomplete="on">
</span>
When enabled, it accepts any string value supported by the HTML input autocomplete
attribute. The value is assigned to the embedding text <input>
, which means it follows form autofill rules and configs set in the browser level. For example, most of the browsers require the input to have a name
and/or id
attribute. Some browsers, like Firefox, demand the input to be a descendant of a <form>
element.
Please refer to the HTML documentation and the developer guideline of each browser for more information (i.e., MDN docs here).
The input-class
The input-class
is assigned to the text input within the component as well.
<vue-timepicker input-class="my-awesome-picker"></vue-timepicker>
<span class="vue__time-picker time-picker">
<input class="display-time my-awesome-picker" type="text" readonly="readonly">
</span>
Start from v1.0.4
, besides String format, input-class
accepts value in Array and Object type as well.
<vue-timepicker input-class="your-awesome-timepicker i-am-vue2-timepicker"></vue-timepicker>
<vue-timepicker :input-class="['your-awesome-timepicker', 'i-am-vue2-timepicker']"></vue-timepicker>
<vue-timepicker :input-class="{
'your-awesome-timepicker': true,
'foo': false,
'i-am-vue2-timepicker': true,
'bar': false
}"></vue-timepicker>
<span class="vue__time-picker time-picker">
<input class="display-time your-awesome-timepicker i-am-vue2-timepicker" type="text" readonly="readonly">
</span>
The input-width
The input-width
helps you to adjust both the <input>
and the dropdown picker's width without overriding the CSS style on your own. It accepts any valid CSS width values like 8em
, 200px
, etc.
<vue-timepicker input-width="100px"></vue-timepicker>
<vue-timepicker input-width="12em" format="HH:mm:ss"></vue-timepicker>
Events API
Event | Arguments | Description |
---|
input | (value) | Emit after value changes |
change | (eventData) | Emit after value changes |
open | | Emit when the dropdown opens |
close | | Emit when the dropdown closes |
focus | | Emit when the user start focusing on the <input> |
blur | | Emit when the user blurs the <input> |
error | (eventData) | Emit when the input value becomes invalid |
The open
and close
Event of the Dropdown Picker
Help to identify the current status of the dropdown picker
data () {
return {
dropdownStatus: 'closed'
}
}
<p>Dropdown Status: I'm {{dropdownStatus}}!</p>
<vue-timepicker @open="dropdownStatus = 'opened'" @close="dropdownStatus = 'closed'"></vue-timepicker>
The focus
and blur
Event
It works with the Manual Input mode, aimed to identify the focus/blur state of the <input>
box. Specially useful in cases where the dropdown is force hidden by hide-dropdown
.
data () {
return {
focusState: 'blurred'
}
}
<p>Focus State: {{focusState}}</p>
<vue-timepicker manual-input hide-dropdown @focus="focusState = 'focused'" @blur="focusState = 'blurred'"></vue-timepicker>
The error
event
Starts from v.1.1.0+
, Timepicker will emit an error
event when the current input value becomes invalid. E.g., when it contains an hour value that is not in the hour-range
list or a minute value that doesn't fit in the minute-interval
.
<vue-timepicker format="H:mm:ss" v-model="erroredInputSample" :hour-range="[8, 9, 10, 11]" :minute-interval="5" @error="errorHanlder"></vue-timepicker>
data () {
return {
erroredInputSample: { H: '5', mm: '03', ss: '00' }
}
},
methods: {
errorHanlder (eventData) {
console.log(eventData)
}
}
The error
event returns an Array of invalid fields' names. When it returns an empty array []
, it means the current input is valid, and all previous errors are gone
NOTE: Empty value will not be marked as invalid.
Helper CSS Class Names
Started from v.1.1.0+
, Vue Timepicker will add additional CSS classes to the <input>
element base on the state of the current input value.
- invalid: One or more fields containing an invalid or disabled value.
- Additional CSS Style: The
<input>
border turns red. - If you want to mute this red border style, add
"skip-error-style"
to input-class
- is-empty: The input value (v-model) is empty. No additional style.
- all-selected: All fields (hour/minute/second/apm) required by the
format
string are not empty. No additional style.
<timepicker input-class="skip-error-style"></timepicker>
<timepicker :input-class="['skip-error-style', 'your-other-class-names']"></timepicker>
Miscellaneous Props API
Prop | Type | Required | Default Value |
---|
hour-label | String | no | undefined |
minute-label | String | no | undefined |
second-label | String | no | undefined |
apm-label | String | no | undefined |
am-text | String | no | undefined |
pm-text | String | no | undefined |
Customized Picker Labels
You can define customized labels on top of the hour, minute, second, and APM pickers with the following properties: hour-label
, minute-label
, second-label
, and apm-label
.
Furthermore, you can replace those am/pm (or AM/PM) string by setting the am-text
and pm-text
parameters.
Please note that these two parameters only change the labels expose to the users (the UI level). The v-model
value and displayTime
value returned by the change
event (the data level) still use the standard am/pm (AM/PM) format.
<vue-timepicker hour-label="heure" minute-label="minute"></vue-timepicker>
<vue-timepicker hour-label="時" minute-label="分" second-label="秒" apm-label="午" am-text="上午" pm-text="下午" format="h:mm:ss a"></vue-timepicker>
Slots
We introduce three slots in v.1.1.4
to help you customize the clear button, the dropdown button, and the input icon with your own icon/image.
Slot Name | Position | Description |
---|
icon | left | On the lefthand side of the <input> |
clearButton | right | In the same spot of the default clear button |
dropdownButton | right | In the same spot of the default dropdown button |
Please note that Vue v2.6.0+ introduces a significant update of the Named Slots syntax. Check the official documentation for more information.
<vue-timepicker>
<template v-slot:icon>
<img src="$YOUR_ICON_SRC" />
</template>
</vue-timepicker>
<vue-timepicker>
<template v-slot:clearButton>
<img src="$YOUR_CUSTOM_IMAGE_SRC" />
</template>
</vue-timepicker>
<vue-timepicker manual-input hide-dropdown>
<template v-slot:dropdownButton>≣</template>
</vue-timepicker>
Contribution
Please feel free to fork and help developing. Check CONTRIBUTING.md for more details.
Change Log
Detail changes of each release: CHANGELOG.md
License
MIT