Components
Customize the datepicker with your custom components
WARNING
Make sure to properly read the documentation and check the examples on how to pass and configure a custom component. Wrong implementation may result in errors
TIP
You can use css
variables inside custom components if you need to style for the theme
monthYearComponent
Create and use a custom component in the header for month/year select
The component will receive the following props
:
months
:{ value: number; text: string }[]
-> value:0-11
, text: name of the monthyears
:{ value: number; text: string }[]
-> generated array of years based on provided range, text and value are the samefilters
: filters propmonthPicker
: monthPicker propmonth
:number
-> This is the value of the selected monthyear
:number
-> This is the value of the selected yearcustomProps
:Record<string, unknown>
-> Your custom propsinstance
:number
-> In case you are using multiCalendars prop, it will be 1 or 2minDate
:Date | string
-> minDate propmaxDate
:Date | string
-> maxDate prop
Important
To update the month and the year value make sure to emit
the following:
- Month
- Event:
update:month
- Value:
number
- Event:
- Year
- Event:
update:year
- Value:
number
- Event:
- Handler event
- Event:
updateMonthYear
- Value:
boolean
(only when updating year)
- Event:
Code Example
<template>
<Datepicker v-model="date" :month-year-component="monthYear" />
</template>
<script>
import { computed, ref, defineAsyncComponent } from 'vue';
// Lazy load the component we want to pass
const MonthYear = defineAsyncComponent(() => import('./MonthYearCustom.vue'));
export default {
setup() {
const date = ref();
// Return from computed as it is imported
const monthYear = computed(() => MonthYear);
return {
date,
monthYear
}
}
}
</script>
<template>
<div class="month-year-wrapper">
<div class="custom-month-year-component">
<select
class="select-input"
:value="month"
@change="$emit('update:month', +$event.target.value)">
<option
v-for="m in months"
:key="m.value"
:value="m.value">{{ m.text }}</option>
</select>
<select
class="select-input"
:value="year"
@change="$emit('update:year', +$event.target.value)">
<option
v-for="y in years"
:key="y.value"
:value="y.value">{{ y.text }}</option>
</select>
</div>
<div class="icons">
<span class="custom-icon" @click="onPrev"><ChevronLeftIcon /></span>
<span class="custom-icon" @click="onNext"><ChevronRightIcon /></span>
</div>
</div>
</template>
<script>
// Icons used in the example, you can use your custom ones
import ChevronLeftIcon from './ChevronLeftIcon.vue';
import ChevronRightIcon from './ChevronRightIcon.vue';
import { defineComponent } from 'vue';
export default defineComponent({
components: { ChevronLeftIcon, ChevronRightIcon },
emits: ['update:month', 'update:year'],
// Available props
props: {
months: { type: Array, default: () => [] },
years: { type: Array, default: () => [] },
filters: { type: Object, default: null },
monthPicker: { type: Boolean, default: false },
month: { type: Number, default: 0 },
year: { type: Number, default: 0 },
customProps: { type: Object, default: null }
},
setup(props, { emit }) {
const updateMonthYear = (month, year) => {
emit('update:month', month);
emit('update:year', year);
};
const onNext = () => {
let month = props.month;
let year = props.year;
if (props.month === 11) {
month = 0;
year = props.year + 1;
} else {
month += 1;
}
updateMonthYear(month, year);
};
const onPrev = () => {
let month = props.month;
let year = props.year;
if (props.month === 0) {
month = 11;
year = props.year - 1;
} else {
month -= 1;
}
updateMonthYear(month, year);
};
return {
onNext,
onPrev,
};
},
});
</script>
<style lang="scss">
.month-year-wrapper {
display: flex;
align-items: center;
justify-content: center;
}
.custom-month-year-component {
display: flex;
align-items: center;
justify-content: flex-start;
}
.select-input {
margin: 5px 3px;
padding: 5px;
width: auto;
border-radius: 4px;
border-color: var(--dp-border-color);
outline: none;
}
.icons {
display: flex;
}
.custom-icon {
padding: 5px;
display: flex;
height: 25px;
align-items: center;
justify-content: center;
cursor: pointer;
width: 25px;
color: var(--dp-icon-color);
text-align: center;
border-radius: 50%;
svg {
height: 20px;
width: 20px;
}
&:hover {
background: var(--dp-hover-color);
}
}
</style>
timePickerComponent
Create and use a custom component for the time picker
The component will receive the following props
:
hoursIncrement
: hoursIncrement propminutesIncrement
: minutesIncrement propsecondsIncrement
: minutesIncrement propis24
: is24 prophoursGridIncrement
: hoursGridIncrement propminutesGridIncrement
: minutesGridIncrement propsecondsGridIncrement
: secondsGridIncrement propfilters
: filters proptimePicker
: timePicker prophours
:number | [number, number]
-> This is the hours valueminutes
:number | [number, number]
-> This is the minutes valuecustomProps
:Record<string, unknown>
-> Your custom propsnoHoursOverlay
:boolean
-> noHoursOverlay propnoMinutesOverlay
:boolean
-> noMinutesOverlay propnoSecondsOverlay
:boolean
-> noSecondsOverlay propcustomProps
:Record<string, unknown>
-> Your custom propsenableSeconds
:boolean
-> enableSeconds prop
Note: hours
and minutes
values will be arrays if range picker mode is active.
Important
To update the hours and the minutes values make sure to emit
the following:
- Hours
- Event:
update:hours
- Value:
number | [number, number]
- Event:
- Minutes
- Event:
update:minutes
- Value:
number | [number, number]
- Event:
Note: Keep in mind that when you are using the range picker, both values for the time must be emitted. For example if you want to update the second date hours, you will emit
something like this emit('update:hours', [firstValueSaved, newSecondValue])
Code Example
<template>
<Datepicker v-model="date" :time-picker-component="timePicker" />
</template>
<script>
import { computed, ref, defineAsyncComponent } from 'vue';
// Lazy load the component we want to pass
const TimePicker = defineAsyncComponent(() => import('./TimePickerCustom.vue'));
export default {
setup() {
const date = ref();
// Return from computed as it is imported
const timePicker = computed(() => TimePicker);
return {
date,
timePicker
}
}
}
</script>
<template>
<div class="custom-time-picker-component">
<select
class="select-input"
:value="hours"
@change="$emit('update:hours', +$event.target.value)">
<option
v-for="h in hoursArray"
:key="h.value"
:value="h.value">{{ h.text }}</option>
</select>
<select
class="select-input"
:value="minutes"
@change="$emit('update:minutes', +$event.target.value)">
<option
v-for="m in minutesArray"
:key="m.value"
:value="m.value">{{ m.text }}</option>
</select>
</div>
</template>
<script>
import { computed, defineComponent } from 'vue';
export default defineComponent({
emits: ['update:hours', 'update:minutes'],
props: {
hoursIncrement: { type: [Number, String], default: 1 },
minutesIncrement: { type: [Number, String], default: 1 },
is24: { type: Boolean, default: true },
hoursGridIncrement: { type: [String, Number], default: 1 },
minutesGridIncrement: { type: [String, Number], default: 5 },
range: { type: Boolean, default: false },
filters: { type: Object, default: () => ({}) },
minTime: { type: Object, default: () => ({}) },
maxTime: { type: Object, default: () => ({}) },
timePicker: { type: Boolean, default: false },
hours: { type: [Number, Array], default: 0 },
minutes: { type: [Number, Array], default: 0 },
customProps: { type: Object, default: null }
},
setup() {
// Generate array of hours
const hoursArray = computed(() => {
const arr = [];
for (let i = 0; i < 24; i++) {
arr.push({ text: i < 10 ? `0${i}` : i, value: i });
}
return arr;
});
// Generate array of minutes
const minutesArray = computed(() => {
const arr = [];
for (let i = 0; i < 60; i++) {
arr.push({ text: i < 10 ? `0${i}` : i, value: i });
}
return arr;
});
return {
hoursArray,
minutesArray,
};
},
});
</script>
<style lang="scss">
.custom-time-picker-component {
display: flex;
align-items: center;
justify-content: center;
}
.select-input {
margin: 5px 3px;
padding: 5px;
width: 100px;
border-radius: 4px;
border-color: var(--dp-border-color);
outline: none;
}
</style>
actionRowComponent
Create and use a custom component for action row
The component will receive the following props
:
selectText
: selectText propcancelText
: cancelText propinternalModelValue
:Date | [Date, Date]
-> Internal value, will be array if range is activerange
: range proppreviewFormat
: previewFormat propmonthPicker
: monthPicker proptimePicker
: timePicker propmultiCalendars
:boolean
-> multiCalendars propcalendarWidth
:number
-> Calendar widthmenuMount
:boolean
-> True when the parent menu component is mountedcustomProps
:Record<string, unknown>
-> Your custom propsminDate
:Date | string
-> minDate propmaxDate
:Date | string
-> maxDate propenableTimePicker
:boolean
-> enableTimePicker propmaxTime
:{ hours: number | string; minutes: number |stirng; seconds: number | string }
-> maxTime propminTime
:{ hours: number | string; minutes: number |stirng; seconds: number | string }
-> minTime prop
Info
Two events are available from this component to emit
:
selectDate
: Selects the current selectionclosePicker
: Closes the datepicker menu
Code Example
<template>
<Datepicker v-model="date" :action-row-component="actionRow" />
</template>
<script>
import { computed, ref, defineAsyncComponent } from 'vue';
// Lazy load the component we want to pass
const ActionRow = defineAsyncComponent(() => import('./ActionRowCustom.vue'));
export default {
setup() {
const date = ref();
// Return from computed as it is imported
const actionRow = computed(() => ActionRow);
return {
date,
actionRow
}
}
}
</script>
<template>
<div class="custom-action-row">
<p class="current-selection">{{ date }}</p>
<button class="select-button" @click="$emit('selectDate')">Select Date</button>
</div>
</template>
<script>
import { computed, defineComponent } from 'vue';
export default defineComponent({
emits: ['selectDate', 'closePicker'],
props: {
selectText: { type: String, default: 'Select' },
cancelText: { type: String, default: 'Cancel' },
internalModelValue: { type: [Date, Array], default: null },
range: { type: Boolean, default: false },
previewFormat: {
type: [String, Function],
default: () => '',
},
monthPicker: { type: Boolean, default: false },
timePicker: { type: Boolean, default: false },
},
setup(props) {
const date = computed(() => {
if (props.internalModelValue) {
const date = props.internalModelValue.getDate();
const month = props.internalModelValue.getMonth() + 1;
const year = props.internalModelValue.getFullYear();
const hours = props.internalModelValue.getHours();
const minutes = props.internalModelValue.getMinutes();
return `${month}/${date}/${year}, ${hours}:${minutes}`;
}
return '';
});
return {
date,
};
},
});
</script>
<style lang="scss">
.custom-action-row {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.current-selection {
margin: 10px 0 0 0;
}
.select-button {
display: block;
background: transparent;
border: 1px solid var(--dp-success-color);
color: var(--dp-success-color);
border-radius: 4px;
padding: 5px;
margin: 10px;
cursor: pointer;
}
</style>
customProps
If you use a custom component you can pass your custom props from the datepicker via this prop
- Type:
Record<string, unknown>
- Default:
null
Also, you can use the provide function and provide needed props from the parent component
Code Example
<template>
<Datepicker :customProps="customProps" v-model="date" />
</template>
<script>
import { ref, reactive } from 'vue';
export default {
setup() {
const date = ref();
// We can access this object in our custom components
const customProps = reactive({
foo: 'bar',
hello: 'hi'
});
return {
date,
customProps,
}
}
}
</script>