DevExtreme v24.1 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

Multiple Selection

This demo applies different selection modes and date availability options to the Calendar component.

Backend API
<div id="calendar-demo"> <div class="calendar-container"> <dx-calendar #calendar [value]="value" [showWeekNumbers]="true" [selectWeekOnClick]="true" [selectionMode]="selectionMode" [min]="minDateValue" [max]="maxDateValue" [disabledDates]="disabledDates" > </dx-calendar> </div> <div class="options"> <div class="caption">Options</div> <div class="option"> <dx-check-box text="Select week on click" [(value)]="calendar.selectWeekOnClick" > </dx-check-box> </div> <div class="option"> <span>Selection mode</span> <dx-select-box [dataSource]="selectionModes" [(value)]="selectionMode" [inputAttr]="{ 'aria-label': 'Selection Mode' }" > </dx-select-box> </div> <div class="caption option"> <span>Date availability</span> </div> <div class="option"> <dx-check-box text="Set minimum date" [value]="false" (onValueChanged)="setMinDate($event)" > </dx-check-box> </div> <div class="option"> <dx-check-box text="Set maximum date" [value]="false" (onValueChanged)="setMaxDate($event)" > </dx-check-box> </div> <div class="option"> <dx-check-box text="Disable weekends" [value]="false" (onValueChanged)="disableWeekend($event)" > </dx-check-box> </div> <div class="option"> <dx-button text="Clear value" (onClick)="clearValue()"> </dx-button> </div> </div> </div>
import { Component, NgModule, ViewChild, enableProdMode, } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { DxSelectBoxModule, DxCheckBoxModule, DxButtonModule } from 'devextreme-angular'; import { DxCalendarComponent, DxCalendarModule, DxCalendarTypes } from 'devextreme-angular/ui/calendar'; if (!/localhost/.test(document.location.host)) { enableProdMode(); } @Component({ selector: 'demo-app', templateUrl: 'app/app.component.html', styleUrls: ['app/app.component.css'], }) export class AppComponent { @ViewChild(DxCalendarComponent, { static: false }) calendar: DxCalendarComponent; now = new Date(); value = [new Date(), new Date(new Date().getTime() + 1000 * 60 * 60 * 24)]; selectionModes: DxCalendarTypes.CalendarSelectionMode[] = [ 'single', 'multiple', 'range', ]; selectionMode: DxCalendarTypes.CalendarSelectionMode = 'multiple'; minDateValue: Date | null = null; maxDateValue: Date | null = null; disabledDates: Function | null = null; isWeekend(date: Date) { const day = date.getDay(); return day === 0 || day === 6; } setMinDate({ value }) { this.minDateValue = value ? new Date(this.now.getTime() - 1000 * 60 * 60 * 24 * 3) : null; } setMaxDate({ value }) { this.maxDateValue = value ? new Date(this.now.getTime() + 1000 * 60 * 60 * 24 * 3) : null; } disableWeekend({ value }) { this.disabledDates = value ? (data: { view: string, date: Date }) => data.view === 'month' && this.isWeekend(data.date) : null; } clearValue() { this.calendar.instance.clear(); } } @NgModule({ imports: [ BrowserModule, DxSelectBoxModule, DxCalendarModule, DxCheckBoxModule, DxButtonModule, ], declarations: [AppComponent], bootstrap: [AppComponent], }) export class AppModule { } platformBrowserDynamic().bootstrapModule(AppModule);
::ng-deep #calendar-demo { display: flex; } .calendar-container { display: flex; flex-direction: column; flex-grow: 1; align-items: center; justify-content: center; } .caption { font-weight: 500; font-size: 18px; } .options { padding: 20px; background-color: rgba(191, 191, 191, 0.15); } .option { margin-top: 10px; }
// In real applications, you should not transpile code in the browser. // You can see how to create your own application with Angular and DevExtreme here: // https://js.devexpress.com/Documentation/Guide/Angular_Components/Getting_Started/Create_a_DevExtreme_Application/ const componentNames = [ 'accordion', 'action-sheet', 'autocomplete', 'bar-gauge', 'box', 'bullet', 'button-group', 'button', 'calendar', 'chart', 'check-box', 'circular-gauge', 'color-box', 'context-menu', 'data-grid', 'date-box', 'date-range-box', 'defer-rendering', 'diagram', 'draggable', 'drawer', 'drop-down-box', 'drop-down-button', 'file-manager', 'file-uploader', 'filter-builder', 'form', 'funnel', 'gallery', 'gantt', 'html-editor', 'linear-gauge', 'list', 'load-indicator', 'load-panel', 'lookup', 'map', 'menu', 'multi-view', 'nested', 'number-box', 'pie-chart', 'pivot-grid-field-chooser', 'pivot-grid', 'polar-chart', 'popover', 'popup', 'progress-bar', 'radio-group', 'range-selector', 'range-slider', 'recurrence-editor', 'resizable', 'responsive-box', 'sankey', 'scheduler', 'scroll-view', 'select-box', 'slider', 'sortable', 'sparkline', 'speed-dial-action', 'splitter', 'switch', 'tab-panel', 'tabs', 'tag-box', 'text-area', 'text-box', 'tile-view', 'toast', 'toolbar', 'tooltip', 'tree-list', 'tree-map', 'tree-view', 'validation-group', 'validation-summary', 'validator', 'vector-map', ]; window.exports = window.exports || {}; window.config = { transpiler: 'ts', typescriptOptions: { module: 'system', emitDecoratorMetadata: true, experimentalDecorators: true, }, meta: { 'typescript': { 'exports': 'ts', }, 'devextreme/time_zone_utils.js': { 'esModule': true, }, 'devextreme/localization.js': { 'esModule': true, }, 'devextreme/viz/palette.js': { 'esModule': true, }, '@angular/platform-browser-dynamic': { 'esModule': true, }, '@angular/platform-browser': { 'esModule': true, }, '@angular/core': { 'esModule': true, }, '@angular/common': { 'esModule': true, }, '@angular/animations': { 'esModule': true, }, '@angular/forms': { 'esModule': true, }, }, paths: { 'npm:': 'https://unpkg.com/', 'bundles:': '../../../../bundles/', }, map: { 'ts': 'npm:plugin-typescript@4.2.4/lib/plugin.js', 'typescript': 'npm:typescript@4.2.4/lib/typescript.js', /* @angular */ '@angular/compiler': 'bundles:@angular/compiler.umd.js', '@angular/platform-browser-dynamic': 'bundles:@angular/platform-browser-dynamic.umd.js', '@angular/core': 'bundles:@angular/core.umd.js', '@angular/core/primitives/signals': 'bundles:@angular/core.primitives.signals.umd.js', '@angular/common': 'bundles:@angular/common.umd.js', '@angular/common/http': 'bundles:@angular/common-http.umd.js', '@angular/platform-browser': 'bundles:@angular/platform-browser.umd.js', '@angular/platform-browser/animations': 'bundles:@angular/platform-browser.umd.js', '@angular/forms': 'bundles:@angular/forms.umd.js', /* devextreme */ 'devextreme': 'npm:devextreme@24.1.3/cjs', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.13', 'devextreme/bundles/dx.all': 'npm:devextreme@24.1.3/bundles/dx.all.js', 'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.8', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.56', /* devextreme-angular umd maps */ 'devextreme-angular': 'bundles:devextreme-angular/devextreme-angular.umd.js', 'devextreme-angular/core': 'bundles:devextreme-angular/devextreme-angular-core.umd.js', ...componentNames.reduce((acc, name) => { acc[`devextreme-angular/ui/${name}`] = `bundles:devextreme-angular/devextreme-angular-ui-${name}.umd.js`; return acc; }, {}), 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js', 'tslib': 'npm:tslib@2.6.1/tslib.js', 'rxjs': 'npm:rxjs@7.5.3/dist/bundles/rxjs.umd.js', 'rxjs/operators': 'npm:rxjs@7.5.3/dist/cjs/operators/index.js', 'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js', 'luxon': 'npm:luxon@1.28.1/build/global/luxon.min.js', 'es6-object-assign': 'npm:es6-object-assign@1.1.0', '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@7.4.11/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', // Prettier 'prettier/standalone': 'npm:prettier@2.8.8/standalone.js', 'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js', }, packages: { 'app': { main: './app.component.ts', defaultExtension: 'ts', }, 'devextreme': { defaultExtension: 'js', }, 'devextreme/events/utils': { main: 'index', }, 'devextreme/events': { main: 'index', }, 'es6-object-assign': { main: './index.js', defaultExtension: 'js', }, 'rxjs': { defaultExtension: 'js', }, 'rxjs/operators': { defaultExtension: 'js', }, }, packageConfigPaths: [ 'npm:@devextreme/*/package.json', 'npm:@devextreme/runtime@3.0.13/inferno/package.json', 'npm:rxjs@7.5.3/package.json', 'npm:rxjs@7.5.3/operators/package.json', 'npm:devexpress-diagram@2.2.8/package.json', 'npm:devexpress-gantt@4.1.56/package.json', ], }; System.config(window.config); // System.import('@angular/compiler').catch(console.error.bind(console));
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/24.1.3/css/dx.light.css" /> <script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script> <script src="https://unpkg.com/zone.js@0.13.0/dist/zone.js"></script> <script src="https://unpkg.com/reflect-metadata@0.1.13/Reflect.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script src="config.js"></script> <script> System.import("app").catch(console.error.bind(console)); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <demo-app>Loading...</demo-app> </div> </body> </html>

Selection Modes

The selected value or values are stored in the value property. The following selection modes are available:

  • 'single'
    A user can select only a single date at any given time.

  • 'multiple'
    A user can select multiple dates simultaneously.

  • 'range'
    A user can select a range of dates. The first and the last date in the range are stored in the value property.

If you enable selectWeekOnClick in 'multiple' or 'range' modes, users can select a week by clicking on the week number.

Disable and Clear Dates

Use the min and max properties to specify the range of available dates. In this demo, these properties limit the range to three days before and after the current date. Enable the "Set minimum date" and "Set maximum date" checkboxes to apply the properties.

If you need to disable specific dates, use the disabledDates property. Toggle the "Disable weekends" checkbox to see how this setting affects component behavior. You can specify either an array of predefined dates or a function that determines whether a date is available.

When using 'multiple' and 'range' selection modes, the behavior of disabled dates in the Calendar is as follows:

  • If you specify the value property programmatically, disabled dates are selected in the values array.

  • If you use the UI to change selection (click on dates or weeks, the Enter key), you cannot select disabled dates in 'multiple' mode. In 'range' mode, disabled dates cannot start or end a range, but can be included in the middle.

To clear selected values, call the Calendar clear() method.