From c67cc024e2677a838cfdae1298ad2c0466ba5348 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Fri, 17 Jan 2020 12:45:06 +0100 Subject: [PATCH] fix(datepicker): error in IE/Edge for static disabled binding IE/Edge can throw an error for a datepicker input which has a static `disabled` binding. The error is thrown, because static bindings in Ivy are invoked before the element is in the DOM which browsers seem to have an assertion against. --- src/material/datepicker/datepicker-input.ts | 17 +++++++++++++++-- tools/public_api_guard/material/datepicker.d.ts | 3 ++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/material/datepicker/datepicker-input.ts b/src/material/datepicker/datepicker-input.ts index 29bd5b71a1c8..ae8a216e4582 100644 --- a/src/material/datepicker/datepicker-input.ts +++ b/src/material/datepicker/datepicker-input.ts @@ -18,6 +18,7 @@ import { OnDestroy, Optional, Output, + AfterViewInit, } from '@angular/core'; import { AbstractControl, @@ -91,7 +92,12 @@ export class MatDatepickerInputEvent { }, exportAs: 'matDatepickerInput', }) -export class MatDatepickerInput implements ControlValueAccessor, OnDestroy, Validator { +export class MatDatepickerInput implements ControlValueAccessor, OnDestroy, AfterViewInit, + Validator { + + /** Whether the component has been initialized. */ + private _isInitialized: boolean; + /** The datepicker that this input is associated with. */ @Input() set matDatepicker(value: MatDatepicker) { @@ -169,7 +175,10 @@ export class MatDatepickerInput implements ControlValueAccessor, OnDestroy, V } // We need to null check the `blur` method, because it's undefined during SSR. - if (newValue && element.blur) { + // In Ivy static bindings are invoked earlier, before the element is attached to the DOM. + // This can cause an error to be thrown in some browsers (IE/Edge) which assert that the + // element has been inserted. + if (newValue && this._isInitialized && element.blur) { // Normally, native input elements automatically blur if they turn disabled. This behavior // is problematic, because it would mean that it triggers another change detection cycle, // which then causes a changed after checked error if the input element was focused before. @@ -257,6 +266,10 @@ export class MatDatepickerInput implements ControlValueAccessor, OnDestroy, V }); } + ngAfterViewInit() { + this._isInitialized = true; + } + ngOnDestroy() { this._datepickerSubscription.unsubscribe(); this._localeSubscription.unsubscribe(); diff --git a/tools/public_api_guard/material/datepicker.d.ts b/tools/public_api_guard/material/datepicker.d.ts index 73ccfa9891a7..73f33b6ea5db 100644 --- a/tools/public_api_guard/material/datepicker.d.ts +++ b/tools/public_api_guard/material/datepicker.d.ts @@ -170,7 +170,7 @@ export declare class MatDatepickerContent extends _MatDatepickerContentMixinB static ɵfac: i0.ɵɵFactoryDef>; } -export declare class MatDatepickerInput implements ControlValueAccessor, OnDestroy, Validator { +export declare class MatDatepickerInput implements ControlValueAccessor, OnDestroy, AfterViewInit, Validator { _dateAdapter: DateAdapter; _dateFilter: (date: D | null) => boolean; _datepicker: MatDatepicker; @@ -197,6 +197,7 @@ export declare class MatDatepickerInput implements ControlValueAccessor, OnDe _onKeydown(event: KeyboardEvent): void; getConnectedOverlayOrigin(): ElementRef; getPopupConnectionElementRef(): ElementRef; + ngAfterViewInit(): void; ngOnDestroy(): void; registerOnChange(fn: (value: any) => void): void; registerOnTouched(fn: () => void): void;