Skip to content

Commit

Permalink
refactor(material/datepicker): remove TypeScript mixin usages
Browse files Browse the repository at this point in the history
Replaces the final TypeScript mixin used by `MatStartDate` and `MatEndDate` with an internal class.
  • Loading branch information
crisbeto committed Nov 18, 2023
1 parent 00e076e commit c5f8c7b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 20 deletions.
48 changes: 35 additions & 13 deletions src/material/datepicker/date-range-input-parts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
OnInit,
Injector,
DoCheck,
Input,
} from '@angular/core';
import {
NG_VALUE_ACCESSOR,
Expand All @@ -29,12 +30,11 @@ import {
ValidationErrors,
} from '@angular/forms';
import {
CanUpdateErrorState,
mixinErrorState,
MAT_DATE_FORMATS,
DateAdapter,
MatDateFormats,
ErrorStateMatcher,
_ErrorStateTracker,
} from '@angular/material/core';
import {Directionality} from '@angular/cdk/bidi';
import {BACKSPACE, LEFT_ARROW, RIGHT_ARROW} from '@angular/cdk/keycodes';
Expand Down Expand Up @@ -81,14 +81,28 @@ abstract class MatDateRangeInputPartBase<D>
*/
ngControl: NgControl;

/** @docs-private */
abstract updateErrorState(): void;

protected abstract override _validator: ValidatorFn | null;
protected abstract override _assignValueToModel(value: D | null): void;
protected abstract override _getValueFromModel(modelValue: DateRange<D>): D | null;

protected readonly _dir = inject(Directionality, {optional: true});
private _errorStateTracker: _ErrorStateTracker;

/** Object used to control when error messages are shown. */
@Input()
get errorStateMatcher() {
return this._errorStateTracker.matcher;
}
set errorStateMatcher(value: ErrorStateMatcher) {
this._errorStateTracker.matcher = value;
}

/** Whether the input is in an error state. */
get errorState() {
return this._errorStateTracker.errorState;
}
set errorState(value: boolean) {
this._errorStateTracker.errorState = value;
}

constructor(
@Inject(MAT_DATE_RANGE_INPUT_PARENT) public _rangeInput: MatDateRangeInputParent<D>,
Expand All @@ -101,6 +115,13 @@ abstract class MatDateRangeInputPartBase<D>
@Optional() @Inject(MAT_DATE_FORMATS) dateFormats: MatDateFormats,
) {
super(_elementRef, dateAdapter, dateFormats);
this._errorStateTracker = new _ErrorStateTracker(
this._defaultErrorStateMatcher,
null,
this._parentFormGroup,
this._parentForm,
this.stateChanges,
);
}

ngOnInit() {
Expand All @@ -110,11 +131,11 @@ abstract class MatDateRangeInputPartBase<D>
// itself. Usually we can work around it for the CVA, but there's no API to do it for the
// validator. We work around it here by injecting the `NgControl` in `ngOnInit`, after
// everything has been resolved.
// tslint:disable-next-line:no-bitwise
const ngControl = this._injector.get(NgControl, null, {optional: true, self: true});

if (ngControl) {
this.ngControl = ngControl;
this._errorStateTracker.ngControl = ngControl;
}
}

Expand Down Expand Up @@ -149,6 +170,11 @@ abstract class MatDateRangeInputPartBase<D>
return value.length > 0 ? value : element.placeholder;
}

/** Refreshes the error state of the input. */
updateErrorState() {
this._errorStateTracker.updateErrorState();
}

/** Handles `input` events on the input element. */
override _onInput(value: string) {
super._onInput(value);
Expand Down Expand Up @@ -199,8 +225,6 @@ abstract class MatDateRangeInputPartBase<D>
}
}

const _MatDateRangeInputBase = mixinErrorState(MatDateRangeInputPartBase);

/** Input for entering the start date in a `mat-date-range-input`. */
@Directive({
selector: 'input[matStartDate]',
Expand All @@ -224,9 +248,8 @@ const _MatDateRangeInputBase = mixinErrorState(MatDateRangeInputPartBase);
// These need to be specified explicitly, because some tooling doesn't
// seem to pick them up from the base class. See #20932.
outputs: ['dateChange', 'dateInput'],
inputs: ['errorStateMatcher'],
})
export class MatStartDate<D> extends _MatDateRangeInputBase<D> implements CanUpdateErrorState {
export class MatStartDate<D> extends MatDateRangeInputPartBase<D> {
/** Validator that checks that the start date isn't after the end date. */
private _startValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
const start = this._dateAdapter.getValidDateOrNull(
Expand Down Expand Up @@ -337,9 +360,8 @@ export class MatStartDate<D> extends _MatDateRangeInputBase<D> implements CanUpd
// These need to be specified explicitly, because some tooling doesn't
// seem to pick them up from the base class. See #20932.
outputs: ['dateChange', 'dateInput'],
inputs: ['errorStateMatcher'],
})
export class MatEndDate<D> extends _MatDateRangeInputBase<D> implements CanUpdateErrorState {
export class MatEndDate<D> extends MatDateRangeInputPartBase<D> {
/** Validator that checks that the end date isn't before the start date. */
private _endValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
const end = this._dateAdapter.getValidDateOrNull(this._dateAdapter.deserialize(control.value));
Expand Down
11 changes: 4 additions & 7 deletions tools/public_api_guard/material/datepicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@
```ts

import { _AbstractConstructor } from '@angular/material/core';
import { AbstractControl } from '@angular/forms';
import { AfterContentInit } from '@angular/core';
import { AfterViewChecked } from '@angular/core';
import { AfterViewInit } from '@angular/core';
import { AnimationEvent as AnimationEvent_2 } from '@angular/animations';
import { AnimationTriggerMetadata } from '@angular/animations';
import { CanUpdateErrorState } from '@angular/material/core';
import { ChangeDetectorRef } from '@angular/core';
import { ComponentType } from '@angular/cdk/portal';
import { _Constructor } from '@angular/material/core';
import { ControlContainer } from '@angular/forms';
import { ControlValueAccessor } from '@angular/forms';
import { DateAdapter } from '@angular/material/core';
Expand Down Expand Up @@ -676,7 +673,7 @@ export abstract class MatDateSelectionModel<S, D = ExtractDateTypeFromSelection<
}

// @public
export class MatEndDate<D> extends _MatDateRangeInputBase<D> implements CanUpdateErrorState {
export class MatEndDate<D> extends MatDateRangeInputPartBase<D> {
constructor(rangeInput: MatDateRangeInputParent<D>, elementRef: ElementRef<HTMLInputElement>, defaultErrorStateMatcher: ErrorStateMatcher, injector: Injector, parentForm: NgForm, parentFormGroup: FormGroupDirective, dateAdapter: DateAdapter<D>, dateFormats: MatDateFormats);
// (undocumented)
protected _assignValueToModel(value: D | null): void;
Expand All @@ -689,7 +686,7 @@ export class MatEndDate<D> extends _MatDateRangeInputBase<D> implements CanUpdat
// (undocumented)
protected _validator: ValidatorFn | null;
// (undocumented)
static ɵdir: i0.ɵɵDirectiveDeclaration<MatEndDate<any>, "input[matEndDate]", never, { "errorStateMatcher": { "alias": "errorStateMatcher"; "required": false; }; }, { "dateChange": "dateChange"; "dateInput": "dateInput"; }, never, never, false, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<MatEndDate<any>, "input[matEndDate]", never, {}, { "dateChange": "dateChange"; "dateInput": "dateInput"; }, never, never, false, never>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<MatEndDate<any>, [null, null, null, null, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }]>;
}
Expand Down Expand Up @@ -826,7 +823,7 @@ export class MatSingleDateSelectionModel<D> extends MatDateSelectionModel<D | nu
}

// @public
export class MatStartDate<D> extends _MatDateRangeInputBase<D> implements CanUpdateErrorState {
export class MatStartDate<D> extends MatDateRangeInputPartBase<D> {
constructor(rangeInput: MatDateRangeInputParent<D>, elementRef: ElementRef<HTMLInputElement>, defaultErrorStateMatcher: ErrorStateMatcher, injector: Injector, parentForm: NgForm, parentFormGroup: FormGroupDirective, dateAdapter: DateAdapter<D>, dateFormats: MatDateFormats);
// (undocumented)
protected _assignValueToModel(value: D | null): void;
Expand All @@ -841,7 +838,7 @@ export class MatStartDate<D> extends _MatDateRangeInputBase<D> implements CanUpd
// (undocumented)
protected _validator: ValidatorFn | null;
// (undocumented)
static ɵdir: i0.ɵɵDirectiveDeclaration<MatStartDate<any>, "input[matStartDate]", never, { "errorStateMatcher": { "alias": "errorStateMatcher"; "required": false; }; }, { "dateChange": "dateChange"; "dateInput": "dateInput"; }, never, never, false, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<MatStartDate<any>, "input[matStartDate]", never, {}, { "dateChange": "dateChange"; "dateInput": "dateInput"; }, never, never, false, never>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<MatStartDate<any>, [null, null, null, null, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }]>;
}
Expand Down

0 comments on commit c5f8c7b

Please sign in to comment.