Skip to content

DateRangePicker - Add cancel button in dialog mode #16109

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Aug 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ All notable changes for each version of this project will be documented in this

## 20.1.0
### New Features
`IgxDateRangePicker`
- Added cancel button to the dialog, allowing the user to cancel the selection.

- `IgxCarousel`
- Added `select` method overload accepting index.
```ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsBG = {
igx_date_range_picker_date_separator: 'до',
igx_date_range_picker_done_button: 'Завърши',
igx_date_range_picker_cancel_button: 'Отмени',
igx_date_range_picker_last7Days: 'Последните 7 дни',
igx_date_range_picker_currentMonth: 'Текущ месец',
igx_date_range_picker_last30Days: 'Последните 30 дни',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsCS = {
igx_date_range_picker_date_separator: 'na',
igx_date_range_picker_done_button: 'Hotovo',
igx_date_range_picker_cancel_button: 'Zrušit',
igx_date_range_picker_last7Days: 'Posledních 7 dní',
igx_date_range_picker_currentMonth: 'Tento měsíc',
igx_date_range_picker_last30Days: 'Posledních 30 dní',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsDA = {
igx_date_range_picker_date_separator: 'till',
igx_date_range_picker_done_button: 'Færdigt',
igx_date_range_picker_cancel_button: 'Annuller',
igx_date_range_picker_last7Days: 'Sidste 7 dage',
igx_date_range_picker_currentMonth: 'Denne måned',
igx_date_range_picker_last30Days: 'Sidste 30 dage',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsDE = {
igx_date_range_picker_date_separator: 'bis',
igx_date_range_picker_done_button: 'Fertig',
igx_date_range_picker_cancel_button: 'Abbrechen',
igx_date_range_picker_last7Days: 'Letzte 7 Tage',
igx_date_range_picker_currentMonth: 'Aktueller Monat',
igx_date_range_picker_last30Days: 'Letzte 30 Tage',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsES = {
igx_date_range_picker_date_separator: 'a',
igx_date_range_picker_done_button: 'Listo',
igx_date_range_picker_cancel_button: 'Cancelar',
igx_date_range_picker_last7Days: 'Últimos 7 días',
igx_date_range_picker_currentMonth: 'Mes actual',
igx_date_range_picker_last30Days: 'Últimos 30 días',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsFR = {
igx_date_range_picker_date_separator: 'à',
igx_date_range_picker_done_button: 'Terminée',
igx_date_range_picker_cancel_button: 'Annuler',
igx_date_range_picker_last7Days: '7 derniers jours',
igx_date_range_picker_currentMonth: 'Mois en cours',
igx_date_range_picker_last30Days: '30 derniers jours',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsHU = {
igx_date_range_picker_date_separator: '-',
igx_date_range_picker_done_button: 'Kész',
igx_date_range_picker_cancel_button: 'Mégse',
igx_date_range_picker_last7Days: 'Az elmúlt 7 nap',
igx_date_range_picker_currentMonth: 'Aktuális hónap',
igx_date_range_picker_last30Days: 'Az elmúlt 30 nap',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsIT = {
igx_date_range_picker_date_separator: 'a',
igx_date_range_picker_done_button: 'Fine',
igx_date_range_picker_cancel_button: 'Annulla',
igx_date_range_picker_last7Days: 'Ultimi 7 giorni',
igx_date_range_picker_currentMonth: 'Mese corrente',
igx_date_range_picker_last30Days: 'Ultimi 30 giorni',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsJA = {
igx_date_range_picker_date_separator: '~',
igx_date_range_picker_done_button: '完了',
igx_date_range_picker_cancel_button: 'キャンセル',
igx_date_range_picker_last7Days: '過去7日間',
igx_date_range_picker_currentMonth: '今月',
igx_date_range_picker_last30Days: '過去30日間',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsKO = {
igx_date_range_picker_date_separator: '에',
igx_date_range_picker_done_button: '완료',
igx_date_range_picker_cancel_button: '취소',
igx_date_range_picker_last7Days: '지난 7일',
igx_date_range_picker_currentMonth: '이번 달',
igx_date_range_picker_last30Days: '지난 30일',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsNB = {
igx_date_range_picker_date_separator: 'til',
igx_date_range_picker_done_button: 'Ferdig',
igx_date_range_picker_cancel_button: 'Avbryt',
igx_date_range_picker_last7Days: 'Siste 7 dager',
igx_date_range_picker_currentMonth: 'Denne måneden',
igx_date_range_picker_last30Days: 'Siste 30 dager',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsNL = {
igx_date_range_picker_date_separator: 'tot',
igx_date_range_picker_done_button: 'Gereed',
igx_date_range_picker_cancel_button: 'Annuleren',
igx_date_range_picker_last7Days: 'Laatste 7 dagen',
igx_date_range_picker_currentMonth: 'Huidige maand',
igx_date_range_picker_last30Days: 'Laatste 30 dagen',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsPL = {
igx_date_range_picker_date_separator: 'do',
igx_date_range_picker_done_button: 'Gotowe',
igx_date_range_picker_cancel_button: 'Anuluj',
igx_date_range_picker_last7Days: 'Ostatnie 7 dni',
igx_date_range_picker_currentMonth: 'Bieżący miesiąc',
igx_date_range_picker_last30Days: 'Ostatnie 30 dni',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsPT = {
igx_date_range_picker_date_separator: 'para',
igx_date_range_picker_done_button: 'Concluído',
igx_date_range_picker_cancel_button: 'Cancelar',
igx_date_range_picker_last7Days: 'Últimos 7 dias',
igx_date_range_picker_currentMonth: 'Mês atual',
igx_date_range_picker_last30Days: 'Últimos 30 dias',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsRO = {
igx_date_range_picker_date_separator: 'la',
igx_date_range_picker_done_button: 'Gata',
igx_date_range_picker_cancel_button: 'Anulează',
igx_date_range_picker_last7Days: 'Ultimele 7 zile',
igx_date_range_picker_currentMonth: 'Luna curentă',
igx_date_range_picker_last30Days: 'Ultimele 30 de zile',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsSV = {
igx_date_range_picker_date_separator: 'till',
igx_date_range_picker_done_button: 'Färdig',
igx_date_range_picker_cancel_button: 'Avbryt',
igx_date_range_picker_last7Days: 'Senaste 7 dagarna',
igx_date_range_picker_currentMonth: 'Aktuell månad',
igx_date_range_picker_last30Days: 'Senaste 30 dagarna',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsTR = {
igx_date_range_picker_date_separator: '-',
igx_date_range_picker_done_button: 'Bitti',
igx_date_range_picker_cancel_button: 'İptal',
igx_date_range_picker_last7Days: 'Son 7 gün',
igx_date_range_picker_currentMonth: 'Geçerli ay',
igx_date_range_picker_last30Days: 'Son 30 gün',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsZHHANS = {
igx_date_range_picker_date_separator: '至',
igx_date_range_picker_done_button: '完成',
igx_date_range_picker_cancel_button: '取消',
igx_date_range_picker_last7Days: '最近7天',
igx_date_range_picker_currentMonth: '本月',
igx_date_range_picker_last30Days: '最近30天',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IDateRangePickerResourceStrings } from 'igniteui-angular';
export const DateRangePickerResourceStringsZHHANT = {
igx_date_range_picker_date_separator: '到',
igx_date_range_picker_done_button: '完成',
igx_date_range_picker_cancel_button: '取消',
igx_date_range_picker_last7Days: '最近7天',
igx_date_range_picker_currentMonth: '本月',
igx_date_range_picker_last30Days: '最近30天',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export interface IDateRangePickerResourceStrings {
igx_date_range_picker_date_separator?: string;
igx_date_range_picker_done_button?: string;
igx_date_range_picker_cancel_button?: string;
igx_date_range_picker_last7Days?: string;
igx_date_range_picker_currentMonth?: string;
igx_date_range_picker_last30Days?: string;
Expand All @@ -10,9 +11,9 @@ export interface IDateRangePickerResourceStrings {
export const DateRangePickerResourceStringsEN: IDateRangePickerResourceStrings = {
igx_date_range_picker_date_separator: 'to',
igx_date_range_picker_done_button: 'Done',
igx_date_range_picker_cancel_button: 'Cancel',
igx_date_range_picker_last7Days: 'Last 7 Days',
igx_date_range_picker_currentMonth: 'Current Month',
igx_date_range_picker_last30Days: 'Last 30 Days',
igx_date_range_picker_yearToDate: 'Year to Date',

};
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
<ng-template #defaultPickerActions>
@if (closeButtonLabel || todayButtonLabel) {
@if (closeButtonLabel || cancelButtonLabel || todayButtonLabel) {
<div class="igx-date-picker__buttons">
@if (cancelButtonLabel) {
<button
#cancelButton type="button"
igxButton="flat" igxRipple
(click)="calendarCancel.emit({ owner: this})"
>
{{ cancelButtonLabel }}
</button>
}
@if (closeButtonLabel) {
<button
#closeButton
type="button"
igxButton="flat"
igxRipple
(click)="calendarClose.emit({ owner: this })"
(click)="calendarClose.emit({ owner: this})"
>
{{ closeButtonLabel }}
</button>
Expand All @@ -28,7 +37,6 @@
</ng-template>

<igx-calendar></igx-calendar>

@if( usePredefinedRanges || (customRanges?.length || 0) > 0 ){
<igx-predefined-ranges-area
[usePredefinedRanges]="usePredefinedRanges"
Expand All @@ -40,7 +48,7 @@
@if (pickerActions?.template || (closeButtonLabel || todayButtonLabel)) {
<igx-divider></igx-divider>
}
@if (pickerActions?.template || (closeButtonLabel || todayButtonLabel)) {
@if (pickerActions?.template || (closeButtonLabel || cancelButtonLabel || todayButtonLabel)) {
<div class="igx-date-picker__actions">
<ng-container
*ngTemplateOutlet="
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ export class IgxCalendarContainerComponent {
@Output()
public calendarClose = new EventEmitter<IBaseEventArgs>();

@Output()
public calendarCancel = new EventEmitter<IBaseEventArgs>();

@Output()
public todaySelection = new EventEmitter<IBaseEventArgs>();

Expand All @@ -58,6 +61,7 @@ export class IgxCalendarContainerComponent {
public resourceStrings!: IDateRangePickerResourceStrings;
public vertical = false;
public closeButtonLabel: string;
public cancelButtonLabel: string;
public todayButtonLabel: string;
public mode: PickerInteractionMode = PickerInteractionMode.DropDown;
public pickerActions: IgxPickerActionsDirective;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const CSS_CLASS_INPUT_GROUP_REQUIRED = 'igx-input-group--required';
const CSS_CLASS_INPUT_GROUP_INVALID = 'igx-input-group--invalid';
const CSS_CLASS_CALENDAR = 'igx-calendar';
const CSS_CLASS_ICON = 'igx-icon';
const CSS_CLASS_DONE_BUTTON = 'igx-button--flat';
const CSS_CLASS_DIALOG_BUTTON = 'igx-button--flat';
const CSS_CLASS_LABEL = 'igx-input-group__label';
const CSS_CLASS_OVERLAY_CONTENT = 'igx-overlay__content';
const CSS_CLASS_DATE_RANGE = 'igx-date-range-picker';
Expand Down Expand Up @@ -281,7 +281,7 @@ describe('IgxDateRangePicker', () => {
let calendar: DebugElement | Element;
let calendarDays: DebugElement[] | HTMLCollectionOf<Element>;

const selectDateRangeFromCalendar = (sDate: Date, eDate: Date) => {
const selectDateRangeFromCalendar = (sDate: Date, eDate: Date, autoClose:boolean = true) => {
dateRange.open();
fixture.detectChanges();
calendarDays = document.getElementsByClassName(CSS_CLASS_CALENDAR_DATE);
Expand All @@ -301,9 +301,13 @@ describe('IgxDateRangePicker', () => {
if (endIndex !== -1 && endIndex !== startIndex) { // do not click same date twice
UIInteractions.simulateClickAndSelectEvent(calendarDays[endIndex].firstChild as HTMLElement);
}

fixture.detectChanges();
dateRange.close();
fixture.detectChanges();

if (autoClose){
dateRange.close();
fixture.detectChanges();
}
};

describe('Single Input', () => {
Expand Down Expand Up @@ -485,7 +489,7 @@ describe('IgxDateRangePicker', () => {
fixture.detectChanges();
expect(dateRange.collapsed).toBeFalsy();

const doneBtn = document.getElementsByClassName(CSS_CLASS_DONE_BUTTON)[0];
const doneBtn = document.getElementsByClassName(CSS_CLASS_DIALOG_BUTTON)[0];
UIInteractions.simulateClickAndSelectEvent(doneBtn);
tick();
fixture.detectChanges();
Expand All @@ -497,14 +501,46 @@ describe('IgxDateRangePicker', () => {
expect(dateRange.closed.emit).toHaveBeenCalledWith({ owner: dateRange });
}));

it('should show the "Done" button only in dialog mode', fakeAsync(() => {
it('should close the calendar with the "Cancel" button and retain original value', fakeAsync(() => {
fixture.componentInstance.mode = PickerInteractionMode.Dialog;
const orig = { start: new Date(2020, 0, 1), end: new Date(2020, 0, 5) };
fixture.componentInstance.dateRange.value = orig;
fixture.detectChanges();

spyOn(dateRange.closing, 'emit').and.callThrough();
spyOn(dateRange.closed, 'emit').and.callThrough();

dateRange.open();
tick();
fixture.detectChanges();
expect(dateRange.collapsed).toBeFalsy();

selectDateRangeFromCalendar(new Date(2020, 0, 8), new Date(2020, 0, 12), false);

const cancelBtn = document.getElementsByClassName(CSS_CLASS_DIALOG_BUTTON)[0];
UIInteractions.simulateClickAndSelectEvent(cancelBtn);
tick();
fixture.detectChanges();

expect(dateRange.collapsed).toBeTrue();
expect(dateRange.closing.emit).toHaveBeenCalledTimes(1);
expect(dateRange.closing.emit).toHaveBeenCalledWith({ owner: dateRange, cancel: false, event: undefined });
expect(dateRange.closed.emit).toHaveBeenCalledTimes(1);
expect(dateRange.closed.emit).toHaveBeenCalledWith({ owner: dateRange });

expect(fixture.componentInstance.dateRange.value).toEqual(orig);
}));

it('should show the "Done" and "Cancel" buttons only in dialog mode', fakeAsync(() => {
fixture.componentInstance.mode = PickerInteractionMode.Dialog;
fixture.detectChanges();

dateRange.open();
fixture.detectChanges();
let doneBtn = document.getElementsByClassName(CSS_CLASS_DONE_BUTTON)[0];
let doneBtn = document.getElementsByClassName(CSS_CLASS_DIALOG_BUTTON)[0];
let cancelBtn = document.getElementsByClassName(CSS_CLASS_DIALOG_BUTTON)[1];
expect(doneBtn).not.toBe(null);
expect(cancelBtn).not.toBe(null);
dateRange.close();
tick();
fixture.detectChanges();
Expand All @@ -515,8 +551,10 @@ describe('IgxDateRangePicker', () => {
dateRange.open();
tick();
fixture.detectChanges();
doneBtn = document.getElementsByClassName(CSS_CLASS_DONE_BUTTON)[0];
doneBtn = document.getElementsByClassName(CSS_CLASS_DIALOG_BUTTON)[0];
cancelBtn = document.getElementsByClassName(CSS_CLASS_DIALOG_BUTTON)[1];
expect(doneBtn).not.toBeDefined();
expect(cancelBtn).not.toBeDefined();
}));

it('should be able to change the "Done" button text', fakeAsync(() => {
Expand All @@ -525,19 +563,24 @@ describe('IgxDateRangePicker', () => {

dateRange.toggle();
fixture.detectChanges();
let doneBtn = document.getElementsByClassName(CSS_CLASS_DONE_BUTTON)[0];
let doneBtn = document.getElementsByClassName(CSS_CLASS_DIALOG_BUTTON)[1];
let cancelBtn = document.getElementsByClassName(CSS_CLASS_DIALOG_BUTTON)[0];
expect(doneBtn.textContent.trim()).toEqual('Done');
expect(cancelBtn.textContent.trim()).toEqual('Cancel');
dateRange.toggle();
tick();
fixture.detectChanges();

dateRange.doneButtonText = 'Close';
dateRange.cancelButtonText = 'Discard'
fixture.detectChanges();
dateRange.toggle();
tick();
fixture.detectChanges();
doneBtn = document.getElementsByClassName(CSS_CLASS_DONE_BUTTON)[0];
doneBtn = document.getElementsByClassName(CSS_CLASS_DIALOG_BUTTON)[1];
cancelBtn = document.getElementsByClassName(CSS_CLASS_DIALOG_BUTTON)[0];
expect(doneBtn.textContent.trim()).toEqual('Close');
console.log(cancelBtn.textContent.trim());
}));

it('should emit open/close events - open/close methods', fakeAsync(() => {
Expand Down
Loading
Loading