3.x
Getting Started

Usage

Render a calendar, read the bound value and configure it.

A first calendar

Bind the calendar with v-model. Without a selection mode it only displays dates, so turn one on.

Bound value
<script setup>
import { ref } from 'vue'
import { FunctionalCalendar } from 'vue-functional-calendar'
import 'vue-functional-calendar/style.css'

const value = ref({})
</script>

<template>
  <FunctionalCalendar v-model="value" is-date-picker />
</template>

Selection modes

PropWhat users pick
isDatePickerOne date.
isMultipleDatePickerAny number of single dates.
isDateRangeOne range with a start and an end.
isDateRange with isMultipleDateRangeSeveral ranges.

The bound value

The calendar keeps its whole state in one object. Which keys matter depends on the mode.

ModeWhere the value lives
Date pickerselectedDate, a string in dateFormat. With the time picker, also selectedDateTime, selectedHour and selectedMinute.
Multiple date pickerselectedDates, a list of { date, dateTime, hour, minute }.
Date rangedateRange.start and dateRange.end.
Multiple date rangemultipleDateRange, a list of { start, end }.

currentDate is a Date in the month on display. selectedDatesItem is the text in the tags input.

The calendar edits the object it receives and emits that same object. Typed dates, time picker changes and the clear button update it in place, without an update:modelValue event. A bound plain object that lacks calendar keys, such as {}, stays your object: the calendar fills in the missing keys when it mounts. Assigning a new {} object later clears the selection. A readonly or frozen object, a non-plain value, and an object holding only multipleDateRange are read into the calendar's own state and are never written to. If you want every key from the start, begin with a full model:

const value = ref({
  currentDate: new Date(),
  selectedDate: false,
  selectedDateTime: false,
  selectedHour: '00',
  selectedMinute: '00',
  selectedDatesItem: '',
  selectedDates: [],
  dateRange: { start: '', end: '' },
  multipleDateRange: [],
})

Date strings use dateFormat, which is dd/mm/yyyy hh:MM by default. Day and month are not padded, so you read 5/3/2026.

Listen to events

<FunctionalCalendar
  v-model="value"
  is-date-range
  @choseDay="day => console.log(day.date)"
  @selectedDaysCount="count => console.log(count)"
  @changedMonth="date => console.log(date)"
/>

See events for every payload.

Configure with props or configs

Pass props one by one, or group them in a configs object. When you pass configs, the calendar reads its settings from there and ignores the matching props.

<FunctionalCalendar
  v-model="value"
  :configs="{ isDateRange: true, dateFormat: 'yyyy-mm-dd', showWeekNumbers: true }"
/>

Props are read once

The calendar reads most props when it is created. Changing isDateRange or locale afterwards has no effect. Re-key the component to rebuild it.

<FunctionalCalendar :key="locale" :locale="locale" is-date-picker v-model="value" />

modelValue and the data props are watched, so changing those works on a live calendar. The data props are markedDates, markedDateRange, disabledDates, enabledDates, disabledDayNames, limits, calendarsCount and isDark. The same keys inside configs are watched too.

Call methods

Use a template ref to move the calendar from code.

<script setup>
const calendar = ref(null)
</script>

<template>
  <FunctionalCalendar ref="calendar" v-model="value" />
  <button @click="calendar.PreMonth()">Previous</button>
  <button @click="calendar.NextMonth()">Next</button>
  <button @click="calendar.ChooseDate('today')">Today</button>
</template>

PreMonth, NextMonth, PreYear and NextYear take an optional calendar index. ChooseDate takes a date in dateFormat or the word today, and moves the calendar there. It refuses a month outside limits.

Copyright © 2026