Skip to content

Align Date & Date Range Picker props related to calendar with WC #16141

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

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
df36861
feat(drp): use templates for calendar header parts as DP + test
ddaribo Aug 11, 2025
0fe1c0f
chore(dp): add calendar header templates to public api dirs array
ddaribo Aug 11, 2025
e7553e7
refactor(picker-base): port headerOrientation prop in base class+test…
ddaribo Aug 11, 2025
999a915
feat(picker-base): add hideHeader prop + tests
ddaribo Aug 11, 2025
37fd4d4
feat(dp, drp): add orientation property + tests
ddaribo Aug 11, 2025
b94049e
feat(drp): limit displayMonthsCount between 1 and 2
ddaribo Aug 11, 2025
062203d
feat(drp): add specialDates prop + test
ddaribo Aug 12, 2025
93cb0b0
feat(drp): add disabledDates prop + test
ddaribo Aug 12, 2025
bdf35c1
feat(dp): update calendar selection on typing + test
ddaribo Aug 13, 2025
bcdb253
refactor(calendar): don't block selection for disabled date through m…
ddaribo Aug 13, 2025
f3c0c78
feat(dp): add activeDate property + tests
ddaribo Aug 13, 2025
0cb144b
refactor(dp): align the calendar activeDate with WC
ddaribo Aug 13, 2025
5b4821b
feat(dp): update calendar days view on typing & value is another view…
ddaribo Aug 13, 2025
62cfb04
fix(drp): check start and end values for disabledDates validation
ddaribo Aug 13, 2025
cc7b014
feat(drp): align activeDate behavior with WC + tests
ddaribo Aug 13, 2025
c0858a8
feat(drp): typing a single value results in calendar range of single …
ddaribo Aug 13, 2025
dd21608
feat(drp-sample): add WC drp + properties panel for manual testing
ddaribo Aug 13, 2025
421e62a
chore(changelog): update with new features for DRP & DP
ddaribo Aug 14, 2025
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
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,40 @@

All notable changes for each version of this project will be documented in this file.

## Unreleased
### New Features

- `IgxDateRangePicker`
- Now has a complete set of properties to customize the calendar:
- `headerOrientation`
- `orientation`
- `hideHeader`
- `activeDate`
- `disabledDates`
- `specialDates`

- As well as the following templates, available to customize the contents of the calendar header in `dialog` mode:

- `igxCalendarHeader`
- `igxCalendarHeaderTitle`
- `igxCalendarSubheader`
- **Behavioral Changes**
- The calendar would be displayed with header in `dialog` mode by default.
- The picker would remain open when typing (in two-inputs and `dropdown` mode).
- The calendar selection would get updated with the typed value.
- The calendar view would be updated as per the typed value.
- The picker would display a clear icon by default in single input mode.
- `IgxDatePicker`
- Similar to the `IgxDateRangePicker`, also completes the ability to customize the calendar by introducing the following
properties in addition to the existing ones:
- `hideHeader`
- `orientation`
- `activeDate`
- **Behavioral Changes**
- The calendar selection would get updated with the typed value.
- The calendar view would be updated as per the typed date value.


## 20.1.0
### New Features
- `IgxCarousel`
Expand Down
8 changes: 3 additions & 5 deletions projects/igniteui-angular/src/lib/calendar/calendar-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -707,15 +707,15 @@ export class IgxCalendarBaseDirective implements ControlValueAccessor {

switch (this.selection) {
case CalendarSelection.SINGLE:
if (isDate(value) && !this.isDateDisabled(value as Date)) {
if (isDate(value)) {
this.selectSingle(value as Date);
}
break;
case CalendarSelection.MULTI:
this.selectMultiple(value);
break;
case CalendarSelection.RANGE:
this.selectRange(value, true);
this.selectRange(value);
break;
}
}
Expand Down Expand Up @@ -807,9 +807,7 @@ export class IgxCalendarBaseDirective implements ControlValueAccessor {
: [value, this.lastSelectedDate];

const unselectedDates = [this._startDate, ...this.generateDateRange(this._startDate, this._endDate)]
.filter(date => !this.isDateDisabled(date)
&& this.selectedDates.every((d: Date) => d.getTime() !== date.getTime())
);
.filter(date => this.selectedDates.every((d: Date) => d.getTime() !== date.getTime()));

// select all dates from last selected to shift clicked date
if (this.selectedDates.some((date: Date) => date.getTime() === this.lastSelectedDate.getTime())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1767,7 +1767,8 @@ describe("IgxCalendar - ", () => {
});

it("Should not select date from model, if it is part of disabled dates", () => {
expect(calendar.value).toBeFalsy();
// Changed per WC alignment task #16131 - calendar should not block selection of dates through API/model
expect(calendar.value).toBeTruthy();
});

it("Should not select date from model in range selection, if model passes null", () => {
Expand Down
42 changes: 28 additions & 14 deletions projects/igniteui-angular/src/lib/calendar/common/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,34 @@ export function getClosestActiveDate(
* @remarks
* By default, `unit` is set to 'day'.
*/
export function* calendarRange(options: CalendarRangeParams) {
let low = toCalendarDay(options.start);
const unit = options.unit ?? "day";
const high =
typeof options.end === "number"
? low.add(unit, options.end)
: toCalendarDay(options.end);

const reverse = high.lessThan(low);
const step = reverse ? -1 : 1;

while (!reverse ? low.lessThan(high) : low.greaterThan(high)) {
yield low;
low = low.add(unit, step);
export function* calendarRange(
options: CalendarRangeParams
): Generator<CalendarDay, void, unknown> {
const { start, end, unit = 'day', inclusive = false } = options;

let currentDate = toCalendarDay(start);
const endDate =
typeof end === 'number'
? toCalendarDay(start).add(unit, end)
: toCalendarDay(end);

const isReversed = endDate.lessThan(currentDate);
const step = isReversed ? -1 : 1;

const shouldContinue = () => {
if (inclusive) {
return isReversed
? currentDate.greaterThanOrEqual(endDate)
: currentDate.lessThanOrEqual(endDate);
}
return isReversed
? currentDate.greaterThan(endDate)
: currentDate.lessThan(endDate);
};

while (shouldContinue()) {
yield currentDate;
currentDate = currentDate.add(unit, step);
}
}

Expand Down
8 changes: 8 additions & 0 deletions projects/igniteui-angular/src/lib/calendar/common/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export type CalendarRangeParams = {
start: DayParameter;
end: DayParameter | number;
unit?: DayInterval;
inclusive?: boolean;
};

type CalendarDayParams = {
Expand Down Expand Up @@ -237,11 +238,18 @@ export class CalendarDay {
public greaterThan(value: DayParameter) {
return this.timestamp > toCalendarDay(value).timestamp;
}
public greaterThanOrEqual(value: DayParameter) {
return this.timestamp >= toCalendarDay(value).timestamp;
}

public lessThan(value: DayParameter) {
return this.timestamp < toCalendarDay(value).timestamp;
}

public lessThanOrEqual(value: DayParameter) {
return this.timestamp <= toCalendarDay(value).timestamp;
}

public toString() {
return `${this.native}`;
}
Expand Down
13 changes: 13 additions & 0 deletions projects/igniteui-angular/src/lib/core/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,19 @@ export const isEqual = (obj1, obj2): boolean => {
return obj1 === obj2;
};

/**
* Limits a number to a range between a minimum and a maximum value.
*
* @param number
* @param min
* @param max
* @returns: `number`
* @hidden
*/
export const clamp = (number: number, min: number, max: number) =>
Math.max(min, Math.min(number, max));


/**
* Utility service taking care of various utility functions such as
* detecting browser features, general cross browser DOM manipulation, etc.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { IBaseCancelableBrowserEventArgs, IBaseEventArgs } from '../core/utils';
import { IgxOverlayOutletDirective } from '../directives/toggle/toggle.directive';
import { OverlaySettings } from '../services/overlay/utilities';
import { IgxPickerToggleComponent } from './picker-icons.common';
import { PickerInteractionMode } from './types';
import { PickerHeaderOrientation, PickerInteractionMode } from './types';
import { WEEKDAYS } from '../calendar/calendar';
import { DateRange } from '../date-range-picker/date-range-picker-inputs.common';
import { IGX_INPUT_GROUP_TYPE, IgxInputGroupType } from '../input-group/inputGroupType';
Expand Down Expand Up @@ -78,6 +78,28 @@ export abstract class PickerBaseDirective implements IToggleView, EditorProvider
@Input()
public mode: PickerInteractionMode = PickerInteractionMode.DropDown;

/**
* Gets/Sets the orientation of the `IgxDatePickerComponent` header.
*
* @example
* ```html
* <igx-date-picker headerOrientation="vertical"></igx-date-picker>
* ```
*/
@Input()
public headerOrientation: PickerHeaderOrientation = PickerHeaderOrientation.Horizontal;

/**
* Gets/Sets whether the header is hidden in dialog mode.
*
* @example
* ```html
* <igx-date-picker mode="dialog" [hideHeader]="true"></igx-date-picker>
* ```
*/
@Input({ transform: booleanAttribute })
public hideHeader = false;

/**
* Overlay settings used to display the pop-up element.
*
Expand Down
7 changes: 7 additions & 0 deletions projects/igniteui-angular/src/lib/date-common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ export const PickerHeaderOrientation = {
} as const;
export type PickerHeaderOrientation = (typeof PickerHeaderOrientation)[keyof typeof PickerHeaderOrientation];

/** Calendar orientation. */
export const PickerCalendarOrientation = {
Horizontal: 'horizontal',
Vertical: 'vertical'
} as const;
export type PickerCalendarOrientation = (typeof PickerCalendarOrientation)[keyof typeof PickerCalendarOrientation];

/**
* This enumeration is used to configure whether the date/time picker has an editable input with drop down
* or is readonly - the date/time is selected only through a dialog.
Expand Down
Loading
Loading