From 450389e28f3afb1f87b1ec8b21c919ad5c19fd10 Mon Sep 17 00:00:00 2001
From: Miles Malerba
Date: Tue, 3 Oct 2017 15:03:12 -0700
Subject: [PATCH] fix(datepicker): use disabled state from FormControl
---
src/demo-app/datepicker/datepicker-demo.html | 22 ++++++++--
src/demo-app/datepicker/datepicker-demo.ts | 5 ++-
src/lib/datepicker/datepicker-input.ts | 4 +-
src/lib/datepicker/datepicker-toggle.ts | 43 +++++++++++---------
src/lib/datepicker/datepicker.spec.ts | 14 ++++++-
src/lib/datepicker/datepicker.ts | 2 +-
6 files changed, 63 insertions(+), 27 deletions(-)
diff --git a/src/demo-app/datepicker/datepicker-demo.html b/src/demo-app/datepicker/datepicker-demo.html
index 127c5ec2bc8d..03de75ca83de 100644
--- a/src/demo-app/datepicker/datepicker-demo.html
+++ b/src/demo-app/datepicker/datepicker-demo.html
@@ -94,14 +94,30 @@ Input disabled datepicker
-Input disabled, datepicker popup enabled
+Input disabled via FormControl
-
+
+
+
+
+
+
+Input disabled, datepicker popup enabled
+
+
+
+
-
diff --git a/src/demo-app/datepicker/datepicker-demo.ts b/src/demo-app/datepicker/datepicker-demo.ts
index fe363d322b5e..974ea3ec4e63 100644
--- a/src/demo-app/datepicker/datepicker-demo.ts
+++ b/src/demo-app/datepicker/datepicker-demo.ts
@@ -1,5 +1,6 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
-import {MatDatepickerInputEvent} from '@angular/material';
+import {FormControl} from '@angular/forms';
+import {MatDatepickerInputEvent} from '@angular/material/datepicker';
@Component({
@@ -26,4 +27,6 @@ export class DatepickerDemo {
onDateInput = (e: MatDatepickerInputEvent) => this.lastDateInput = e.value;
onDateChange = (e: MatDatepickerInputEvent) => this.lastDateChange = e.value;
+
+ dateCtrl = new FormControl();
}
diff --git a/src/lib/datepicker/datepicker-input.ts b/src/lib/datepicker/datepicker-input.ts
index fc3fee065f54..290e5202445f 100644
--- a/src/lib/datepicker/datepicker-input.ts
+++ b/src/lib/datepicker/datepicker-input.ts
@@ -147,7 +147,7 @@ export class MatDatepickerInput implements AfterContentInit, ControlValueAcce
/** Whether the datepicker-input is disabled. */
@Input()
- get disabled() { return this._disabled; }
+ get disabled() { return !!this._disabled; }
set disabled(value: any) {
const newValue = coerceBooleanProperty(value);
@@ -289,7 +289,7 @@ export class MatDatepickerInput implements AfterContentInit, ControlValueAcce
// Implemented as part of ControlValueAccessor
setDisabledState(disabled: boolean): void {
- this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', disabled);
+ this.disabled = disabled;
}
_onKeydown(event: KeyboardEvent) {
diff --git a/src/lib/datepicker/datepicker-toggle.ts b/src/lib/datepicker/datepicker-toggle.ts
index ff84a574f3a2..4b49c32e2c9b 100644
--- a/src/lib/datepicker/datepicker-toggle.ts
+++ b/src/lib/datepicker/datepicker-toggle.ts
@@ -6,7 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
+import {coerceBooleanProperty} from '@angular/cdk/coercion';
import {
+ AfterContentInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
@@ -16,12 +18,11 @@ import {
SimpleChanges,
ViewEncapsulation,
} from '@angular/core';
-import {MatDatepicker} from './datepicker';
-import {MatDatepickerIntl} from './datepicker-intl';
-import {coerceBooleanProperty} from '@angular/cdk/coercion';
-import {Subscription} from 'rxjs/Subscription';
import {merge} from 'rxjs/observable/merge';
import {of as observableOf} from 'rxjs/observable/of';
+import {Subscription} from 'rxjs/Subscription';
+import {MatDatepicker} from './datepicker';
+import {MatDatepickerIntl} from './datepicker-intl';
@Component({
@@ -35,7 +36,7 @@ import {of as observableOf} from 'rxjs/observable/of';
preserveWhitespaces: false,
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class MatDatepickerToggle implements OnChanges, OnDestroy {
+export class MatDatepickerToggle implements AfterContentInit, OnChanges, OnDestroy {
private _stateChanges = Subscription.EMPTY;
/** Datepicker instance that the button will toggle. */
@@ -44,28 +45,18 @@ export class MatDatepickerToggle implements OnChanges, OnDestroy {
/** Whether the toggle button is disabled. */
@Input()
get disabled(): boolean {
- return this._disabled === undefined ? this.datepicker.disabled : this._disabled;
+ return this._disabled === undefined ? this.datepicker.disabled : !!this._disabled;
}
- set disabled(value) {
+ set disabled(value: boolean) {
this._disabled = coerceBooleanProperty(value);
}
private _disabled: boolean;
- constructor(
- public _intl: MatDatepickerIntl,
- private _changeDetectorRef: ChangeDetectorRef) {}
+ constructor(public _intl: MatDatepickerIntl, private _changeDetectorRef: ChangeDetectorRef) {}
ngOnChanges(changes: SimpleChanges) {
if (changes.datepicker) {
- const datepicker: MatDatepicker = changes.datepicker.currentValue;
- const datepickerDisabled = datepicker ? datepicker._disabledChange : observableOf();
- const inputDisabled = datepicker && datepicker._datepickerInput ?
- datepicker._datepickerInput._disabledChange :
- observableOf();
-
- this._stateChanges.unsubscribe();
- this._stateChanges = merge(this._intl.changes, datepickerDisabled, inputDisabled)
- .subscribe(() => this._changeDetectorRef.markForCheck());
+ this._watchStateChanges();
}
}
@@ -73,10 +64,24 @@ export class MatDatepickerToggle implements OnChanges, OnDestroy {
this._stateChanges.unsubscribe();
}
+ ngAfterContentInit() {
+ this._watchStateChanges();
+ }
+
_open(event: Event): void {
if (this.datepicker && !this.disabled) {
this.datepicker.open();
event.stopPropagation();
}
}
+
+ private _watchStateChanges() {
+ const datepickerDisabled = this.datepicker ? this.datepicker._disabledChange : observableOf();
+ const inputDisabled = this.datepicker && this.datepicker._datepickerInput ?
+ this.datepicker._datepickerInput._disabledChange : observableOf();
+
+ this._stateChanges.unsubscribe();
+ this._stateChanges = merge(this._intl.changes, datepickerDisabled, inputDisabled)
+ .subscribe(() => this._changeDetectorRef.markForCheck());
+ }
}
diff --git a/src/lib/datepicker/datepicker.spec.ts b/src/lib/datepicker/datepicker.spec.ts
index dfcf2df0a509..919539a44db3 100644
--- a/src/lib/datepicker/datepicker.spec.ts
+++ b/src/lib/datepicker/datepicker.spec.ts
@@ -25,6 +25,7 @@ import {NoopAnimationsModule} from '@angular/platform-browser/animations';
import {MatInputModule} from '../input/index';
import {MatDatepicker} from './datepicker';
import {MatDatepickerInput} from './datepicker-input';
+import {MatDatepickerToggle} from './datepicker-toggle';
import {MatDatepickerIntl, MatDatepickerModule} from './index';
@@ -539,6 +540,15 @@ describe('MatDatepicker', () => {
expect(inputEl.disabled).toBe(true);
});
+
+ it('should disable toggle when form control disabled', () => {
+ expect(testComponent.datepickerToggle.disabled).toBe(false);
+
+ testComponent.formControl.disable();
+ fixture.detectChanges();
+
+ expect(testComponent.datepickerToggle.disabled).toBe(true);
+ });
});
describe('datepicker with mat-datepicker-toggle', () => {
@@ -582,7 +592,7 @@ describe('MatDatepicker', () => {
});
it('should not open calendar when toggle clicked if input is disabled', () => {
- expect(testComponent.datepicker.disabled).toBeUndefined();
+ expect(testComponent.datepicker.disabled).toBe(false);
testComponent.input.disabled = true;
fixture.detectChanges();
@@ -1120,6 +1130,7 @@ class DatepickerWithNgModel {
@Component({
template: `
+
`,
})
@@ -1127,6 +1138,7 @@ class DatepickerWithFormControl {
formControl = new FormControl();
@ViewChild('d') datepicker: MatDatepicker;
@ViewChild(MatDatepickerInput) datepickerInput: MatDatepickerInput;
+ @ViewChild(MatDatepickerToggle) datepickerToggle: MatDatepickerToggle;
}
diff --git a/src/lib/datepicker/datepicker.ts b/src/lib/datepicker/datepicker.ts
index 0793be2dc4e5..0ad4789b2f4a 100644
--- a/src/lib/datepicker/datepicker.ts
+++ b/src/lib/datepicker/datepicker.ts
@@ -149,7 +149,7 @@ export class MatDatepicker implements OnDestroy {
@Input()
get disabled() {
return this._disabled === undefined && this._datepickerInput ?
- this._datepickerInput.disabled : this._disabled;
+ this._datepickerInput.disabled : !!this._disabled;
}
set disabled(value: any) {
const newValue = coerceBooleanProperty(value);