If you have technical questions, please create a support ticket in the DevExpress Support Center.
import React, { useCallback, useState } from 'react';
import CheckBox from 'devextreme-react/check-box';
import SelectBox from 'devextreme-react/select-box';
import DateBox from 'devextreme-react/date-box';
import Calendar, { CalendarTypes } from 'devextreme-react/calendar';
import CustomCell from './CustomCell.tsx';
const zoomLevels = ['month', 'year', 'decade', 'century'];
const weekNumberRules = ['auto', 'firstDay', 'firstFourDays', 'fullWeek'];
const weekDays = [
{ id: 0, text: 'Sunday' },
{ id: 1, text: 'Monday' },
{ id: 2, text: 'Tuesday' },
{ id: 3, text: 'Wednesday' },
{ id: 4, text: 'Thursday' },
{ id: 5, text: 'Friday' },
{ id: 6, text: 'Saturday' },
];
const dateBoxLabel = { 'aria-label': 'Date' };
const zoomLevelLabel = { 'aria-label': 'Zoom Level' };
const dayLabel = { 'aria-label': 'First Day of Week' };
const ruleLabel = { 'aria-label': 'Week Number Rule' };
export default function App() {
const [zoomLevel, setZoomLevel] = useState<CalendarTypes.CalendarZoomLevel>('month');
const [currentValue, setCurrentValue] = useState(new Date());
const [useCellTemplate, setUseCellTemplate] = useState(null);
const [disabled, setDisabled] = useState(false);
const [showWeekNumbers, setShowWeekNumbers] = useState(false);
const [firstDay, setFirstDay] = useState<CalendarTypes.FirstDayOfWeek>(0);
const [weekNumberRule, setWeekNumberRule] = useState<CalendarTypes.WeekNumberRule>('auto');
const onCurrentValueChange = useCallback(
({ value }) => {
setCurrentValue(value);
},
[setCurrentValue],
);
const onDisabledChange = useCallback(
({ value }) => {
setDisabled(value);
},
[setDisabled],
);
const onZoomLevelChange = useCallback(
({ value }) => {
setZoomLevel(value);
},
[setZoomLevel],
);
const onFirstDayChange = useCallback(
({ value }) => {
setFirstDay(value);
},
[setFirstDay],
);
const onWeekNumberRuleChange = useCallback(
({ value }) => {
setWeekNumberRule(value);
},
[setWeekNumberRule],
);
const onShowWeekNumbersChange = useCallback(
({ value }) => {
setShowWeekNumbers(value);
},
[setShowWeekNumbers],
);
const onUseCellTemplateChange = useCallback(
({ value }) => {
setUseCellTemplate(!!value);
},
[setUseCellTemplate],
);
const onOptionChange = useCallback(
(e: { name: string }) => {
if (e.name === 'zoomLevel') {
onZoomLevelChange(e);
}
},
[onZoomLevelChange],
);
return (
<div id="calendar-demo">
<div className="calendar-container">
<Calendar
value={currentValue}
onValueChanged={onCurrentValueChange}
onOptionChanged={onOptionChange}
firstDayOfWeek={firstDay}
weekNumberRule={weekNumberRule}
showWeekNumbers={showWeekNumbers}
disabled={disabled}
zoomLevel={zoomLevel}
cellComponent={useCellTemplate ? CustomCell : null}
/>
</div>
<div className="options">
<div className="caption">Options</div>
<div className="option">
<span>Zoom level</span>
<SelectBox
dataSource={zoomLevels}
value={zoomLevel}
inputAttr={zoomLevelLabel}
onValueChanged={onZoomLevelChange}
/>
</div>
<div className="option">
<span>Selected date</span>
<DateBox
id="selected-date"
value={currentValue}
onValueChanged={onCurrentValueChange}
inputAttr={dateBoxLabel}
/>
</div>
<div className="option">
<CheckBox
defaultValue={false}
text="Use custom cell template"
onValueChanged={onUseCellTemplateChange}
/>
</div>
<div className="option">
<CheckBox
value={disabled}
text="Disable the calendar"
onValueChanged={onDisabledChange}
/>
</div>
<div className="caption option">
<span>Week numeration</span>
</div>
<div className="option">
<CheckBox
defaultValue={false}
text="Show week numbers"
onValueChanged={onShowWeekNumbersChange}
/>
</div>
<div className="option">
<span>First day of week</span>
<SelectBox
dataSource={weekDays}
inputAttr={dayLabel}
displayExpr="text"
valueExpr="id"
value={firstDay}
onValueChanged={onFirstDayChange}
/>
</div>
<div className="option">
<span>Week number rule</span>
<SelectBox
dataSource={weekNumberRules}
inputAttr={ruleLabel}
value={weekNumberRule}
onValueChanged={onWeekNumberRuleChange}
/>
</div>
</div>
</div>
);
}
xxxxxxxxxx
import React, { useCallback, useState } from 'react';
import CheckBox from 'devextreme-react/check-box';
import SelectBox from 'devextreme-react/select-box';
import DateBox from 'devextreme-react/date-box';
import Calendar from 'devextreme-react/calendar';
import CustomCell from './CustomCell.js';
const zoomLevels = ['month', 'year', 'decade', 'century'];
const weekNumberRules = ['auto', 'firstDay', 'firstFourDays', 'fullWeek'];
const weekDays = [
{ id: 0, text: 'Sunday' },
{ id: 1, text: 'Monday' },
{ id: 2, text: 'Tuesday' },
{ id: 3, text: 'Wednesday' },
{ id: 4, text: 'Thursday' },
{ id: 5, text: 'Friday' },
{ id: 6, text: 'Saturday' },
];
const dateBoxLabel = { 'aria-label': 'Date' };
const zoomLevelLabel = { 'aria-label': 'Zoom Level' };
const dayLabel = { 'aria-label': 'First Day of Week' };
const ruleLabel = { 'aria-label': 'Week Number Rule' };
export default function App() {
const [zoomLevel, setZoomLevel] = useState('month');
const [currentValue, setCurrentValue] = useState(new Date());
const [useCellTemplate, setUseCellTemplate] = useState(null);
const [disabled, setDisabled] = useState(false);
const [showWeekNumbers, setShowWeekNumbers] = useState(false);
const [firstDay, setFirstDay] = useState(0);
const [weekNumberRule, setWeekNumberRule] = useState('auto');
const onCurrentValueChange = useCallback(
({ value }) => {
setCurrentValue(value);
},
[setCurrentValue],
);
const onDisabledChange = useCallback(
({ value }) => {
setDisabled(value);
},
[setDisabled],
);
const onZoomLevelChange = useCallback(
({ value }) => {
setZoomLevel(value);
},
[setZoomLevel],
);
const onFirstDayChange = useCallback(
({ value }) => {
setFirstDay(value);
},
[setFirstDay],
);
const onWeekNumberRuleChange = useCallback(
({ value }) => {
setWeekNumberRule(value);
},
[setWeekNumberRule],
);
const onShowWeekNumbersChange = useCallback(
({ value }) => {
setShowWeekNumbers(value);
},
[setShowWeekNumbers],
);
const onUseCellTemplateChange = useCallback(
({ value }) => {
setUseCellTemplate(!!value);
},
[setUseCellTemplate],
);
const onOptionChange = useCallback(
(e) => {
if (e.name === 'zoomLevel') {
onZoomLevelChange(e);
}
},
[onZoomLevelChange],
);
return (
<div id="calendar-demo">
<div className="calendar-container">
<Calendar
value={currentValue}
onValueChanged={onCurrentValueChange}
onOptionChanged={onOptionChange}
firstDayOfWeek={firstDay}
weekNumberRule={weekNumberRule}
showWeekNumbers={showWeekNumbers}
disabled={disabled}
zoomLevel={zoomLevel}
cellComponent={useCellTemplate ? CustomCell : null}
/>
</div>
<div className="options">
<div className="caption">Options</div>
<div className="option">
<span>Zoom level</span>
<SelectBox
dataSource={zoomLevels}
value={zoomLevel}
inputAttr={zoomLevelLabel}
onValueChanged={onZoomLevelChange}
/>
</div>
<div className="option">
<span>Selected date</span>
<DateBox
id="selected-date"
value={currentValue}
onValueChanged={onCurrentValueChange}
inputAttr={dateBoxLabel}
/>
</div>
<div className="option">
<CheckBox
defaultValue={false}
text="Use custom cell template"
onValueChanged={onUseCellTemplateChange}
/>
</div>
<div className="option">
<CheckBox
value={disabled}
text="Disable the calendar"
onValueChanged={onDisabledChange}
/>
</div>
<div className="caption option">
<span>Week numeration</span>
</div>
<div className="option">
<CheckBox
defaultValue={false}
text="Show week numbers"
onValueChanged={onShowWeekNumbersChange}
/>
</div>
<div className="option">
<span>First day of week</span>
<SelectBox
dataSource={weekDays}
inputAttr={dayLabel}
displayExpr="text"
valueExpr="id"
value={firstDay}
onValueChanged={onFirstDayChange}
/>
</div>
<div className="option">
<span>Week number rule</span>
<SelectBox
dataSource={weekNumberRules}
inputAttr={ruleLabel}
value={weekNumberRule}
onValueChanged={onWeekNumberRuleChange}
/>
</div>
</div>
</div>
);
}
xxxxxxxxxx
import React from 'react';
export function isWeekend(date: Date) {
const day = date.getDay();
return day === 0 || day === 6;
}
function getCellCssClass({ date, view }) {
let cssClass = '';
const holidays = [
[1, 0],
[4, 6],
[25, 11],
];
if (view === 'month') {
if (!date) {
cssClass = 'week-number';
} else {
if (isWeekend(date)) {
cssClass = 'weekend';
}
holidays.forEach((item) => {
if (date.getDate() === item[0] && date.getMonth() === item[1]) {
cssClass = 'holiday';
}
});
}
}
return cssClass;
}
function CustomCell({ data: cell }) {
const { text } = cell;
const className = getCellCssClass(cell);
return <span className={className}>{text}</span>;
}
export default CustomCell;
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
ReactDOM.render(<App />, document.getElementById('app'));
xxxxxxxxxx
window.exports = window.exports || {};
window.config = {
transpiler: 'ts',
typescriptOptions: {
module: 'system',
emitDecoratorMetadata: true,
experimentalDecorators: true,
jsx: 'react',
},
meta: {
'react': {
'esModule': true,
},
'typescript': {
'exports': 'ts',
},
'devextreme/time_zone_utils.js': {
'esModule': true,
},
'devextreme/localization.js': {
'esModule': true,
},
'devextreme/viz/palette.js': {
'esModule': true,
},
'openai': {
'esModule': true,
},
},
paths: {
'npm:': 'https://unpkg.com/',
'bundles:': 'bundles/',
'externals:': 'bundles/externals/',
},
defaultExtension: 'js',
map: {
'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js',
'typescript': 'npm:typescript@4.2.4/lib/typescript.js',
'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js',
'react': 'npm:react@17.0.2/umd/react.development.js',
'react-dom': 'npm:react-dom@17.0.2/umd/react-dom.development.js',
'prop-types': 'npm:prop-types/prop-types.js',
'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign',
'devextreme': 'npm:devextreme@link:../../packages/devextreme/artifacts/npm/devextreme/cjs',
'devextreme-react': 'npm:devextreme-react@link:../../packages/devextreme-react/npm/cjs',
'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.5/dist/dx-diagram.js',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.54/dist/dx-gantt.js',
'@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12',
'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate/dist/inferno-hydrate.min.js',
'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
'devextreme-cldr-data': 'npm:devextreme-cldr-data@1.0.3',
// SystemJS plugins
'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js',
'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',
// Prettier
'prettier/standalone': 'npm:prettier@2.8.8/standalone.js',
'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js',
},
packages: {
'devextreme': {
defaultExtension: 'js',
},
'devextreme-react': {
main: 'index.js',
},
'devextreme/events/utils': {
main: 'index',
},
'devextreme/localization/messages': {
format: 'json',
defaultExtension: 'json',
},
'devextreme/events': {
main: 'index',
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js',
},
},
packageConfigPaths: [
'npm:@devextreme/*/package.json',
'npm:@devextreme/runtime@3.0.12/inferno/package.json',
],
babelOptions: {
sourceMaps: false,
stage0: true,
react: true,
},
};
System.config(window.config);
xxxxxxxxxx
import React from 'react';
export function isWeekend(date) {
const day = date.getDay();
return day === 0 || day === 6;
}
function getCellCssClass({ date, view }) {
let cssClass = '';
const holidays = [
[1, 0],
[4, 6],
[25, 11],
];
if (view === 'month') {
if (!date) {
cssClass = 'week-number';
} else {
if (isWeekend(date)) {
cssClass = 'weekend';
}
holidays.forEach((item) => {
if (date.getDate() === item[0] && date.getMonth() === item[1]) {
cssClass = 'holiday';
}
});
}
}
return cssClass;
}
function CustomCell({ data: cell }) {
const { text } = cell;
const className = getCellCssClass(cell);
return <span className={className}>{text}</span>;
}
export default CustomCell;
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
ReactDOM.render(<App />, document.getElementById('app'));
xxxxxxxxxx
<html lang="en">
<head></head>
<body class="dx-viewport">
<div class="demo-container">
<div id="app"></div>
</div>
</body>
</html>
xxxxxxxxxx
#calendar-demo {
display: flex;
}
.calendar-container {
display: flex;
flex-direction: column;
flex-grow: 1;
align-items: center;
justify-content: center;
}
.dx-calendar-cell:not(.dx-calendar-other-month) .weekend,
.dx-calendar-cell:not(.dx-calendar-other-month) .holiday {
text-shadow: none;
font-weight: bold;
}
.dx-calendar-cell:not(.dx-calendar-other-month) .weekend {
color: #3030ff;
}
.dx-state-disabled.dx-calendar .dx-calendar-cell:not(.dx-calendar-other-month) .weekend {
color: #8080ff;
}
.dx-calendar-cell:not(.dx-calendar-other-month) .holiday {
color: #ff3030;
}
.dx-state-disabled.dx-calendar .dx-calendar-cell:not(.dx-calendar-other-month) .holiday {
color: #ff8080;
}
.dx-calendar-week-number-cell .week-number {
font-style: italic;
}
.caption {
font-weight: 500;
font-size: 18px;
}
.options {
padding: 20px;
background-color: rgba(191, 191, 191, 0.15);
}
.option {
margin-top: 10px;
}
When you add a Calendar to an application, you need to specify its value in one of the following formats:
-
Date
Specifies the date directly. -
Number
Specifies the date with a timestamp (total milliseconds since 1970/01/01). -
String
Specifies the date with a string value. The UI component supports the following formats of a date string:- "yyyy-MM-dd" (for example, "2017-03-06")
- "yyyy-MM-ddTHH:mm:ss" (for example, "2017-03-27T16:54:48")
- "yyyy-MM-ddTHH:mm:ssZ" (for example, "2017-03-27T13:55:41Z")
- "yyyy-MM-ddTHH:mm:ssx" (for example, "2017-03-27T16:54:10+03")
-
Array of the formats mentioned before
Available only for 'multiple' and 'range' selection modes. The array includes all selected dates.
Specify First Day of Week and Display Week Numbers
To specify the first day of the week, assign its index (0 - for Sunday, 1 - for Monday, and so on) to the firstDayOfWeek property. You can also display a column with week numbers. For this, enable the showWeekNumbers property.
The start of the first week of the year depends on the locale. If you want to apply a specific rule, use the weekNumberRule property.
Handle Value Change
Set the onValueChanged property to handle the value change. In this demo, the DateBox and the Calendar both use this property to pass values between each other, and you can use one of these components to change the date.
Customize Cell Appearance
Use the cellTemplate property to customize cell appearance. In this demo, the following customizations are applied when you toggle the "Use custom cell template" checkbox:
-
All the weekends on the Calendar become blue.
-
All the holidays become red.
-
If a column with week numbers is shown, week numbers are italicized.
You can set your own function that changes the class of the span element that contains cell text.
Other Customizations
Set the disabled property to disable the Calendar.
To specify the initial calendar view (month, year, decade, or century), set the zoomLevel property.