Calendar / Datepicker
Calendar is a touch optimized component that provides an easy way to handle dates.
Calendar could be used as inline component or as overlay. Overlay Calendar will be automatically converted to Popover on tablets (iPad).
Calendar App Methods
Let's look at related App methods to work with Calendar:
app.calendar.create(parameters)- create Calendar instance
- parameters - object. Object with calendar parameters
Method returns created Calendar's instance
app.calendar.destroy(el)- destroy Calendar instance
- el - HTMLElement or string (with CSS Selector) or object. Calendar element or Calendar instance to destroy.
app.calendar.get(el)- get Calendar instance by HTML element
- el - HTMLElement or string (with CSS Selector). Calendar element.
Method returns Calendar's instance
app.calendar.close(el)- close Calendar
- el - HTMLElement or string (with CSS Selector). Calendar element to close.
Method returns Calendar's instance
For example:
var calendar = app.calendar.create({
inputEl: '#calendar-input'
});
Calendar Parameters
Let's look on list of all available Calendar parameters:
Parameter | Type | Default | Description |
---|---|---|---|
locale | string | Calendar locale. Should be a correct locale accepted by For example | |
value | array | Array with initial selected dates. Each array item represents selected date | |
disabled | Date Range | Additional disabled dates. Parameter accepts so called Date Range (look below for details) | |
events | Date Range | Dates with events. Will be marked with additional "dot" on calendar day. Parameter accepts so called Date Range (look below for details). If you want to indicate that day has few different events, it is possible to indicate this with multiple different color dots. In this case, you need to pass date range as array where each object will have
| |
rangesClasses | array | Date ranges you want to add custom CSS class for additional styling. Look below for accepted format | |
formatValue | function (values) | Function to format input value, should return new/formatted string value. values is an array where each item represents selected date. Can be used instead of dateFormat parameter to specify custom formatting | |
monthNames | array | auto | Array with full month names. If auto then it will display month names based on specified locale (or browser locale) |
monthNamesShort | array | auto | Array with short month names. If auto then it will display month names based on specified locale (or browser locale) |
dayNames | array | auto | Array with week day names. If auto then it will display day names based on specified locale (or browser locale) |
dayNamesShort | array | auto | Array with week day short names. If auto then it will day names based on specified locale (or browser locale) |
firstDay | number | 1 | First day of the week. By default 1 - Monday |
weekendDays | array | [0, 6] | Array with index numeber of weekend days, by default it is Saturday and Sunday |
dateFormat | string object | undefined | If undefined, it will use format based on It can accept For example Or you can pass string with special tokens, available expressions:
The following additional time expressions available when
|
multiple | boolean | false | Enable to allows select multiple dates/values |
rangePicker | boolean | false | Enable to enable range picker. Not compatible with multiple |
rangePickerMinDays | number | 1 | Minimum days that need to be selected when rangePicker enabled |
rangePickerMaxDays | number | 0 | Maximum days allowed to be selected when rangePicker enabled. 0 means no maximum |
direction | string | 'horizontal' | Months layout direction, could be 'horizontal' or 'vertical' |
minDate | Date | null | Minimum allowed date |
maxDate | Date | null | Maximum allowed date |
touchMove | boolean | true | If enabled then calendar months slides follow finger during touch move |
animate | boolean | true | Enables transition between months |
closeOnSelect | boolean | false | Enable and calendar will be closed when user pick a date |
weekHeader | boolean | true | Enable week header with short name week days |
monthSelector | boolean | true | Enable month selector in toolbar |
monthPicker | boolean | true | Enables month picker to select a month when clicked on a month selector in toolbar |
yearSelector | boolean | true | Enable year picker in toolbar |
yearPicker | boolean | true | Enables year picker to select a year when clicked on a year selector in toolbar |
yearPickerMin | number | Minimum available year for year picker, by default is today minus 100 years | |
yearPickerMax | number | Maximum available year for year picker, by default is today plus 100 years | |
timePicker | boolean | false | Enables time picker. |
timePickerFormat | object | {hour: 'numeric', minute: 'numeric'} | Time format displayed in time selector. It accepts
|
timePickerPlaceholder | string | Select time | Text to display in time selector placeholder. |
Container/opener-specific parameters | |||
containerEl | string HTMLElement | String with CSS selector or HTMLElement where to place generated Calendar HTML. Use only for inline calendar | |
openIn | string | auto | Can be auto , popover (to open calendar in popover), sheet (to open in sheet modal) or customModal (to open in custom Calendar modal overlay). In case of auto will open in sheet modal on small screens and in popover on large screens. |
sheetPush | boolean | false | Enables Calendar sheet to push view/s behind on open |
sheetSwipeToClose | boolean | undefined | Enables ability to close Calendar sheet with swipe. When not specified it inherits app's Sheet swipeToClose parameter |
inputEl | string or HTMLElement | String with CSS selector or HTMLElement with related input element | |
scrollToInput | boolean | true | Scroll viewport (page-content) to input when calendar opened |
inputReadOnly | boolean | true | Sets "readonly" attribute on specified input |
cssClass | string | Additional CSS class name to be set on calendar element | |
closeByOutsideClick | boolean | true | If enabled, picker will be closed by clicking outside of picker or related input element |
toolbar | boolean | true | Enables calendar toolbar |
toolbarCloseText | string | Done | Text for Done/Close toolbar button |
header | boolean | false | Enables calendar header |
headerPlaceholder | string | Select date | Default calendar header placeholder text |
routableModals | boolean | false | Will add opened calendar to router history which gives ability to close calendar by going back in router history and set current route to the calendar modal |
url | string | date/ | Calendar modal URL that will be set as a current route |
view | object | View where to set routing when routableModals enabled. Defaults to parent view of inputEl or main view if not found parent view | |
backdrop | boolean | Enables Calendar backdrop (dark semi transparent layer behind). By default only it is enabled when Calendar opened in Popover. | |
closeByBackdropClick | boolean | true | When enabled, Calendar will be closed on backdrop click |
Render Functions | |||
renderWeekHeader | function | Function to render week header. Must return week header HTML string | |
renderMonths | function(date) | Function to render months wrapper. Must return months container full HTML string | |
renderMonth | function(date, offset) | Function to render single month. Must return single month HTML string | |
renderMonthSelector | function | Function to render month selector. Must return month selector HTML string | |
renderYearSelector | function | Function to render year selector. Must return year selector HTML string | |
renderHeader | function | Function to render calendar header. Must return calendar header HTML string | |
renderToolbar | function | Function to render toolbar. Must return toolbar HTML string | |
render | function | Function to render whole calendar. Must return calendar full HTML string | |
Events | |||
on | object | Object with events handlers. For example:
|
Note that all following parameters can be used in global app parameters under calendar
property to set defaults for all calendars. For example:
var app = new Framework7({
calendar: {
url: 'calendar/',
dateFormat: 'dd.mm.yyyy',
}
});
Date Range
Some of Calendar parameters (disabled, events and rangesClasses) accept so called Date Range. It is a simple way to specify and cover all possible dates combination.
It can be array with dates, for example:
var calendar = app.calendar.create({
...
// Disabled 10th November 2015 and 11th November 2015:
disabled: [new Date(2015, 10, 10), new Date(2015, 10, 11)],
...
});
It can be custom function where you need to return true or false
var calendar = app.calendar.create({
...
//Disabled all dates in November 2015
disabled: function (date) {
if (date.getFullYear() === 2015 && date.getMonth() === 10) {
return true;
}
else {
return false;
}
},
...
});
Or object with from and to properties
var calendar = app.calendar.create({
...
//Disable all dates between 1st October 2015 and 31 December 2015
disabled: {
from: new Date(2015, 9, 1),
to: new Date(2015, 11, 31)
},
...
});
Or object with just from or to properties
var calendar = app.calendar.create({
...
//Disable everyting since December 2015
disabled: {
from: new Date(2015, 11, 1)
},
...
});
Or object with date
property:
var calendar = app.calendar.create({
...
// Disabled 1th December 2015
disabled: {
date: new Date(2015, 11, 1)
},
...
});
Or array with mixed dates and objects:
var calendar = app.calendar.create({
...
events: [
new Date(2015, 9, 1),
new Date(2015, 9, 5),
{
from: new Date(2015, 9, 10),
to: new Date(2015, 9, 15)
},
{
from: new Date(2015, 9, 20),
to: new Date(2015, 9, 31)
},
{
date: new Date(2015, 11, 1),
color: '#ff0000'
},
// same date but one more color dot will be added
{
date: new Date(2015, 11, 1),
color: '#00ff00'
},
],
...
});
rangesClasses
rangesClasses parameter accepts array of objects with Date Range and class names for this range:
var calendar = app.calendar.create({
...
//Add classes for november and october
rangesClasses: [
//Add "day-october' class for all october dates
{
// string CSS class name for this range in "cssClass" property
cssClass: 'day-october', //string CSS class
// Date Range in "range" property
range: function (date) {
return date.getMonth() === 9
}
},
//Add "day-holiday" class for 1-10th January 2016
{
cssClass: 'day-holiday',
range: {
from: new Date(2016, 0, 1),
to: new Date(2016, 0, 10)
}
}
],
...
});
Calendar Methods & Properties
After we initialize Calendar we have its initialized instance in variable (like calendar
variable in examples above) with helpful methods and properties:
Properties | |
---|---|
calendar.app | Link to global app instance |
calendar.containerEl | Calendar wrapping container HTML element (when inline calendar is in use) |
calendar.$containerEl | Dom7 instance with calendar wrapping container HTML element (when inline calendar is in use) |
calendar.el | Calendar HTML element |
calendar.$el | Dom7 instance with calendar HTML element |
calendar.inputEl | Calendar input HTML element (passed in inputEl parameter) |
calendar.$inputEl | Dom7 instance with calendar input HTML element (passed in inputEl parameter) |
calendar.value | Array where each item represents selected date |
calendar.currentMonth | Calendar view current month. Number, from 0 to 11 |
calendar.currentYear | Calendar view current year. Number, for example 2020 |
calendar.opened | true if Calendar is currently opened |
calendar.inline | true when inline calendar is in use |
calendar.cols | Array with specified Calendar columns. Each column also has its own methods and properties (look below) |
calendar.url | Calendar URL (that was passed in url parameter) |
calendar.view | Calendar View (that was passed in view parameter) or found parent view |
calendar.params | Object with initialization parameters |
calendar.allowTouchMove | Set this flag to false to prevent touch move interactions after initialization |
Methods | |
calendar.setValue(values) | Set new selected dates. values is array where each item represents selected date |
calendar.getValue() | Returns current calendar value |
calendar.addValue() | Adds value to the values array. Useful in case if multiple selection is enabled (with multiple: true parameter) |
calendar.update() | Rerenders calendar. Useful in case you added/changed values dynamically and need to update calendar layout |
calendar.nextMonth(duration) | Calendar transition to next month for specified duration in ms |
calendar.prevMonth(duration) | Calendar transition to previous month for specified duration in ms |
calendar.nextYear() | Calendar transition to next year |
calendar.prevYear() | Calendar transition to previous year |
calendar.setYearMonth(year, month, duration) | Calendar transition to specified year , month for specified duration in ms |
calendar.open() | Open Calendar |
calendar.close() | Close Calendar |
calendar.destroy() | Destroy Calendar instance and remove all events |
calendar.on(event, handler) | Add event handler |
calendar.once(event, handler) | Add event handler that will be removed after it was fired |
calendar.off(event, handler) | Remove event handler |
calendar.off(event) | Remove all handlers for specified event |
calendar.emit(event, ...args) | Fire event on instance |
Calendar Events
Calendar will fire the following DOM events on calendar element and events on app and calendar instance:
DOM Events
Event | Target | Description |
---|---|---|
calendar:open | Calendar Element<div class="calendar"> | Event will be triggered when Calendar starts its opening animation |
calendar:opened | Calendar Element<div class="calendar"> | Event will be triggered after Calendar completes its opening animation |
calendar:close | Calendar Element<div class="calendar"> | Event will be triggered when Calendar starts its closing animation |
calendar:closed | Calendar Element<div class="calendar"> | Event will be triggered after Calendar completes its closing animation |
App and Calendar Instance Events
Calendar instance emits events on both self instance and app instance. App instance events has same names prefixed with calendar
.
Event | Target | Arguments | Description |
---|---|---|---|
dayClick | calendar | (calendar, dayEl, year, month, day) | Event will be triggered after click on calendar day element |
calendarDayClick | app | ||
change | calendar | (calendar, value) | Event will be triggered when calendar value changes |
calendarChange | app | ||
monthAdd | calendar | (calendar, monthEl) | Event will be triggered when new month HTML layout has been added. Useful if you need to postprocess added html elements |
calendarMonthAdd | app | ||
monthYearChangeStart | calendar | (calendar, year, month) | Event will be triggered in the begining of transition to next month |
calendarMonthYearChangeStart | app | ||
monthYearChangeEnd | calendar | (calendar, year, month) | Event will be triggered after transition to next month |
calendarMonthYearChangeEnd | app | ||
init | calendar | (calendar) | Event will be triggered when calendar initialized |
calendarInit | app | ||
open | calendar | (calendar) | Event will be triggered when Calendar starts its opening animation. As an argument event handler receives calendar instance |
calendarOpen | app | ||
opened | calendar | (calendar) | Event will be triggered after Calendar completes its opening animation. As an argument event handler receives calendar instance |
calendarOpened | app | ||
close | calendar | (calendar) | Event will be triggered when Calendar starts its closing animation. As an argument event handler receives calendar instance |
calendarClose | app | ||
closed | calendar | (calendar) | Event will be triggered after Calendar completes its closing animation. As an argument event handler receives calendar instance |
calendarClosed | app | ||
beforeDestroy | calendar | (calendar) | Event will be triggered right before Calendar instance will be destroyed. As an argument event handler receives calendar instance |
calendarBeforeDestroy | app |
CSS Variables
Below is the list of related CSS variables (CSS custom properties).
Note that commented variables are not specified by default and their values is what they fallback to in this case.
:root {
--f7-calendar-height: 340px;
--f7-calendar-sheet-landscape-height: 220px;
--f7-calendar-popover-width: 320px;
--f7-calendar-popover-height: 320px;
--f7-calendar-modal-height: 420px;
--f7-calendar-modal-max-width: 380px;
/*
--f7-calendar-header-bg-color: var(--f7-bars-bg-color);
--f7-calendar-header-link-color: var(--f7-bars-link-color);
--f7-calendar-header-text-color: var(--f7-bars-text-color);
--f7-calendar-footer-bg-color: var(--f7-bars-bg-color);
--f7-calendar-footer-border-color: var(--f7-bars-border-color);
--f7-calendar-footer-link-color: var(--f7-bars-link-color);
--f7-calendar-footer-text-color: var(--f7-bars-text-color);
*/
--f7-calendar-week-header-bg-color: transparent;
--f7-calendar-footer-padding: 0 8px;
--f7-calendar-week-header-font-size: 11px;
/*
--f7-calendar-selected-bg-color: var(--f7-theme-color);
*/
--f7-calendar-disabled-text-color: #d4d4d4;
--f7-calendar-event-dot-size: 4px;
/*
--f7-calendar-event-bg-color: var(--f7-theme-color);
*/
/*
--f7-calendar-picker-selected-text-color: var(--f7-theme-color);
*/
--f7-calendar-time-selector-height: 28px;
--f7-calendar-picker-pressed-bg-color: rgba(0, 0, 0, 0.1);
--f7-calendar-picker-hover-bg-color: rgba(0, 0, 0, 0.03);
--f7-calendar-time-selector-bg-color: rgba(0, 0, 0, 0.05);
}
:root .dark,
:root.dark {
--f7-calendar-picker-pressed-bg-color: rgba(255, 255, 255, 0.08);
--f7-calendar-picker-hover-bg-color: rgba(255, 255, 255, 0.03);
--f7-calendar-time-selector-bg-color: rgba(255, 255, 255, 0.1);
}
.ios {
--f7-calendar-selected-text-color: #fff;
--f7-calendar-header-height: 44px;
--f7-calendar-header-font-size: 17px;
--f7-calendar-header-font-weight: 600;
--f7-calendar-header-padding: 0 8px;
--f7-calendar-footer-height: 44px;
--f7-calendar-footer-font-size: 17px;
--f7-calendar-week-header-height: 18px;
--f7-calendar-day-font-size: 15px;
--f7-calendar-day-size: 30px;
--f7-calendar-picker-font-size: 17px;
--f7-calendar-time-selector-font-size: 17px;
--f7-calendar-modal-border-radius: 4px;
--f7-calendar-modal-box-shadow: 0px 11px 15px -7px rgba(0, 0, 0, 0.2),
0px 24px 38px 3px rgba(0, 0, 0, 0.14),
0px 9px 46px 8px rgba(0, 0, 0, 0.12);
--f7-calendar-prev-next-text-color: #c8c8c8;
--f7-calendar-sheet-border-color: #929499;
--f7-calendar-sheet-bg-color: #fff;
--f7-calendar-week-header-text-color: #5e5e5e;
--f7-calendar-modal-bg-color: #fff;
--f7-calendar-day-text-color: #000;
--f7-calendar-today-text-color: #000;
--f7-calendar-today-bg-color: #e3e3e3;
}
.ios .dark,
.ios.dark {
--f7-calendar-prev-next-text-color: #5e5e5e;
--f7-calendar-sheet-border-color: var(--f7-bars-border-color);
--f7-calendar-sheet-bg-color: #121212;
--f7-calendar-week-header-text-color: #aaa;
--f7-calendar-modal-bg-color: #121212;
--f7-calendar-day-text-color: #fff;
--f7-calendar-today-text-color: #fff;
--f7-calendar-today-bg-color: #333;
}
.md {
--f7-calendar-sheet-border-color: transparent;
--f7-calendar-header-height: 64px;
--f7-calendar-header-font-size: 24px;
--f7-calendar-header-font-weight: 400;
--f7-calendar-header-padding: 0 24px;
--f7-calendar-footer-height: 56px;
--f7-calendar-footer-font-size: 14px;
--f7-calendar-week-header-height: 24px;
--f7-calendar-day-font-size: 14px;
--f7-calendar-today-bg-color: none;
--f7-calendar-day-size: 32px;
--f7-calendar-picker-font-size: 14px;
--f7-calendar-time-selector-font-size: 14px;
--f7-calendar-modal-border-radius: 28px;
--f7-calendar-modal-box-shadow: none;
}
.md,
.md .dark,
.md [class*='color-'] {
--f7-calendar-sheet-bg-color: var(--f7-md-surface-1);
--f7-calendar-selected-text-color: var(--f7-md-on-primary);
--f7-calendar-week-header-text-color: var(--f7-md-on-surface-variant);
--f7-calendar-day-text-color: var(--f7-md-on-surface);
--f7-calendar-prev-next-text-color: rgba(var(--f7-md-on-surface-variant-rgb), 0.55);
--f7-calendar-today-text-color: var(--f7-theme-color);
--f7-calendar-modal-bg-color: var(--f7-md-surface-1);
}
Examples
<template>
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="title">Calendar</div>
</div>
</div>
<div class="page-content">
<div class="block">
<p>Calendar is a touch optimized component that provides an easy way to handle dates.</p>
<p>Calendar could be used as inline component or as overlay. Overlay Calendar will be automatically converted to
Popover on tablets (iPad).</p>
</div>
<div class="block-title">Default setup</div>
<div class="list list-strong-ios list-outline-ios">
<ul>
<li>
<div class="item-content item-input">
<div class="item-inner">
<div class="item-input-wrap">
<input type="text" placeholder="Your birth date" readonly="readonly" id="demo-calendar-default" />
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="block-title">Custom date format</div>
<div class="list list-strong-ios list-outline-ios">
<ul>
<li>
<div class="item-content item-input">
<div class="item-inner">
<div class="item-input-wrap">
<input type="text" placeholder="Select date" readonly="readonly" id="demo-calendar-date-format" />
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="block-title">Date + Time</div>
<div class="list list-strong-ios list-outline-ios">
<ul>
<li>
<div class="item-content item-input">
<div class="item-inner">
<div class="item-input-wrap">
<input type="text" placeholder="Select date and time" readonly="readonly"
id="demo-calendar-date-time" />
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="block-title">Multiple Values</div>
<div class="list list-strong-ios list-outline-ios">
<ul>
<li>
<div class="item-content item-input">
<div class="item-inner">
<div class="item-input-wrap">
<input type="text" placeholder="Select multiple dates" readonly="readonly"
id="demo-calendar-multiple" />
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="block-title">Range Picker</div>
<div class="list list-strong-ios list-outline-ios">
<ul>
<li>
<div class="item-content item-input">
<div class="item-inner">
<div class="item-input-wrap">
<input type="text" placeholder="Select date range" readonly="readonly" id="demo-calendar-range" />
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="block-title">Open in Modal</div>
<div class="list list-strong-ios list-outline-ios">
<ul>
<li>
<div class="item-content item-input">
<div class="item-inner">
<div class="item-input-wrap">
<input type="text" placeholder="Select date" readonly="readonly" id="demo-calendar-modal" />
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="block-title">Calendar Page</div>
<div class="list list-strong list-outline-ios">
<ul>
<li>
<a href="/calendar-page/" class="item-content item-link">
<div class="item-inner">
<div class="item-title">Open Calendar Page</div>
</div>
</a>
</li>
</ul>
</div>
<div class="block-title">Inline with custom toolbar</div>
<div class="block block-strong no-padding">
<div id="demo-calendar-inline-container"></div>
</div>
</div>
</div>
</template>
<script>
export default (props, { $f7, $, $on }) => {
let calendarDefault
let calendarDateFormat;
let calendarDateTime;
let calendarMultiple;
let calendarRange;
let calendarModal;
let calendarInline;
$on('pageInit', () => {
// Default
calendarDefault = $f7.calendar.create({
inputEl: '#demo-calendar-default',
});
// With custom date format
calendarDateFormat = $f7.calendar.create({
inputEl: '#demo-calendar-date-format',
dateFormat: { weekday: 'long', month: 'long', day: '2-digit', year: 'numeric' },
});
// Date + Time
calendarDateTime = $f7.calendar.create({
inputEl: '#demo-calendar-date-time',
timePicker: true,
dateFormat: { month: 'numeric', day: 'numeric', year: 'numeric', hour: 'numeric', minute: 'numeric' },
});
// With multiple values
calendarMultiple = $f7.calendar.create({
inputEl: '#demo-calendar-multiple',
dateFormat: { month: 'short', day: 'numeric' },
multiple: true
});
// Range Picker
calendarRange = $f7.calendar.create({
inputEl: '#demo-calendar-range',
rangePicker: true
});
// Custom modal
calendarModal = $f7.calendar.create({
inputEl: '#demo-calendar-modal',
openIn: 'customModal',
header: true,
footer: true,
});
// Inline with custom toolbar
var monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
calendarInline = $f7.calendar.create({
containerEl: '#demo-calendar-inline-container',
value: [new Date()],
renderToolbar: function () {
return '<div class="toolbar calendar-custom-toolbar no-shadow">' +
'<div class="toolbar-inner">' +
'<div class="left">' +
'<a class="link icon-only"><i class="icon icon-back"></i></a>' +
'</div>' +
'<div class="center"></div>' +
'<div class="right">' +
'<a class="link icon-only"><i class="icon icon-forward"></i></a>' +
'</div>' +
'</div>' +
'</div>';
},
on: {
init: function (c) {
$('.calendar-custom-toolbar .center').text(monthNames[c.currentMonth] + ', ' + c.currentYear);
$('.calendar-custom-toolbar .left .link').on('click', function () {
calendarInline.prevMonth();
});
$('.calendar-custom-toolbar .right .link').on('click', function () {
calendarInline.nextMonth();
});
},
monthYearChangeStart: function (c) {
$('.calendar-custom-toolbar .center').text(monthNames[c.currentMonth] + ', ' + c.currentYear);
}
}
});
});
$on('pageBeforeRemove', () => {
calendarDefault.destroy();
calendarDateFormat.destroy();
calendarDateTime.destroy();
calendarMultiple.destroy();
calendarRange.destroy();
calendarModal.destroy();
calendarInline.destroy();
});
return $render;
};
</script>