diff --git a/src/material/core/datetime/date-selection-model.ts b/src/material/core/datetime/date-selection-model.ts index 39c6c94535b9..60dce0276a5d 100644 --- a/src/material/core/datetime/date-selection-model.ts +++ b/src/material/core/datetime/date-selection-model.ts @@ -7,6 +7,7 @@ */ import {DateAdapter} from '@angular/material/core'; +import {FactoryProvider, Optional, SkipSelf, Injectable} from '@angular/core'; import {Subject, Observable} from 'rxjs'; export abstract class MatDateSelectionModel { @@ -23,6 +24,7 @@ export abstract class MatDateSelectionModel { abstract isComplete(): boolean; abstract isSame(other: MatDateSelectionModel): boolean; abstract isValid(): boolean; + abstract overlaps(range: DateRange): boolean; } export interface DateRange { @@ -33,6 +35,7 @@ export interface DateRange { /** * Concrete implementation of a MatDateSelectionModel that holds a single date. */ +@Injectable() export class MatSingleDateSelectionModel extends MatDateSelectionModel { private _date: D | null = null; @@ -75,12 +78,23 @@ export class MatSingleDateSelectionModel extends MatDateSelectionModel { this._date = date; this._valueChangesSubject.next(); } + + /** + * Determines if the single date is within a given date range. Retuns false if either dates of + * the range is null or if the selection is undefined. + */ + overlaps(range: DateRange): boolean { + return !!(this._date && range.start && range.end && + this.adapter.compareDate(range.start, this._date) <= 0 && + this.adapter.compareDate(this._date, range.end) <= 0); + } } /** * Concrete implementation of a MatDateSelectionModel that holds a date range, represented by * a start date and an end date. */ +@Injectable() export class MatRangeDateSelectionModel extends MatDateSelectionModel { private _start: D | null = null; private _end: D | null = null; @@ -138,4 +152,39 @@ export class MatRangeDateSelectionModel extends MatDateSelectionModel { end: this._end, }; } + + /** + * Returns true if the given range and the selection overlap in any way. False if otherwise, that + * includes incomplete selections or ranges. + */ + overlaps(range: DateRange): boolean { + if (!(this._start && this._end && range.start && range.end)) { + return false; + } + + return ( + this._isBetween(range.start, this._start, this._end) || + this._isBetween(range.end, this._start, this._end) || + ( + this.adapter.compareDate(range.start, this._start) <= 0 && + this.adapter.compareDate(this._end, range.end) <= 0 + ) + ); + } + + private _isBetween(value: D, from: D, to: D): boolean { + return this.adapter.compareDate(from, value) <= 0 && this.adapter.compareDate(value, to) <= 0; + } } + +export function MAT_SINGLE_DATE_SELECTION_MODEL_FACTORY(parent: + MatSingleDateSelectionModel, + adapter: DateAdapter) { + return parent || new MatSingleDateSelectionModel(adapter); +} + +export const MAT_SINGLE_DATE_SELECTION_MODEL_PROVIDER: FactoryProvider = { + provide: MatDateSelectionModel, + deps: [[new Optional(), new SkipSelf(), MatDateSelectionModel], DateAdapter], + useFactory: MAT_SINGLE_DATE_SELECTION_MODEL_FACTORY, +}; diff --git a/tools/public_api_guard/material/core.d.ts b/tools/public_api_guard/material/core.d.ts index 45cf3219ea4c..c753ea451c32 100644 --- a/tools/public_api_guard/material/core.d.ts +++ b/tools/public_api_guard/material/core.d.ts @@ -205,6 +205,10 @@ export declare const MAT_OPTION_PARENT_COMPONENT: InjectionToken; +export declare function MAT_SINGLE_DATE_SELECTION_MODEL_FACTORY(parent: MatSingleDateSelectionModel, adapter: DateAdapter): MatSingleDateSelectionModel; + +export declare const MAT_SINGLE_DATE_SELECTION_MODEL_PROVIDER: FactoryProvider; + export declare class MatCommonModule { constructor(highContrastModeDetector: HighContrastModeDetector, sanityChecks: any); static ɵinj: i0.ɵɵInjectorDef; @@ -233,6 +237,7 @@ export declare abstract class MatDateSelectionModel { abstract isComplete(): boolean; abstract isSame(other: MatDateSelectionModel): boolean; abstract isValid(): boolean; + abstract overlaps(range: DateRange): boolean; } export declare const MATERIAL_SANITY_CHECKS: InjectionToken; @@ -336,7 +341,10 @@ export declare class MatRangeDateSelectionModel extends MatDateSelectionModel isComplete(): boolean; isSame(other: MatDateSelectionModel): boolean; isValid(): boolean; + overlaps(range: DateRange): boolean; setRange(start: D | null, end: D | null): void; + static ɵfac: i0.ɵɵFactoryDef>; + static ɵprov: i0.ɵɵInjectableDef>; } export declare class MatRipple implements OnInit, OnDestroy, RippleTarget { @@ -372,7 +380,10 @@ export declare class MatSingleDateSelectionModel extends MatDateSelectionMode isComplete(): boolean; isSame(other: MatDateSelectionModel): boolean; isValid(): boolean; + overlaps(range: DateRange): boolean; setDate(date: D | null): void; + static ɵfac: i0.ɵɵFactoryDef>; + static ɵprov: i0.ɵɵInjectableDef>; } export declare const JAN = 0, FEB = 1, MAR = 2, APR = 3, MAY = 4, JUN = 5, JUL = 6, AUG = 7, SEP = 8, OCT = 9, NOV = 10, DEC = 11;