feat(datepicker): add opened input binding (#8098)

* Adds support for the `opened` input binding.

Closes #8094
This commit is contained in:
Paul Gschwendtner
2017-11-29 20:17:01 +01:00
committed by tinayuangao
parent 9e35bf0e21
commit 2b9bc5769a
2 changed files with 57 additions and 35 deletions
+49 -30
View File
@@ -28,7 +28,6 @@ import {MatDatepickerInput} from './datepicker-input';
import {MatDatepickerToggle} from './datepicker-toggle';
import {MatDatepickerIntl, MatDatepickerModule} from './index';
describe('MatDatepicker', () => {
const SUPPORTS_INTL = typeof Intl != 'undefined';
@@ -113,6 +112,18 @@ describe('MatDatepicker', () => {
.not.toBeNull();
});
it('should open datepicker if opened input is set to true', () => {
testComponent.opened = true;
fixture.detectChanges();
expect(document.querySelector('.mat-datepicker-content')).not.toBeNull();
testComponent.opened = false;
fixture.detectChanges();
expect(document.querySelector('.mat-datepicker-content')).toBeNull();
});
it('open in disabled mode should not open the calendar', () => {
testComponent.disabled = true;
fixture.detectChanges();
@@ -151,9 +162,7 @@ describe('MatDatepicker', () => {
testComponent.datepicker.close();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(parseInt(getComputedStyle(popup).height as string)).toBe(0);
});
expect(parseInt(getComputedStyle(popup).height as string)).toBe(0);
});
it('should close the popup when pressing ESCAPE', () => {
@@ -177,7 +186,7 @@ describe('MatDatepicker', () => {
.toBe(true, 'Expected default ESCAPE action to be prevented.');
});
it('close should close dialog', () => {
it('close should close dialog', async(() => {
testComponent.touch = true;
fixture.detectChanges();
@@ -192,9 +201,9 @@ describe('MatDatepicker', () => {
fixture.whenStable().then(() => {
expect(document.querySelector('mat-dialog-container')).toBeNull();
});
});
}));
it('setting selected should update input and close calendar', () => {
it('setting selected should update input and close calendar', async(() => {
testComponent.touch = true;
fixture.detectChanges();
@@ -212,12 +221,13 @@ describe('MatDatepicker', () => {
expect(document.querySelector('mat-dialog-container')).toBeNull();
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 2));
});
});
}));
it('clicking the currently selected date should close the calendar ' +
'without firing selectedChanged', () => {
const selectedChangedSpy =
spyOn(testComponent.datepicker.selectedChanged, 'emit').and.callThrough();
for (let changeCount = 1; changeCount < 3; changeCount++) {
const currentDay = changeCount;
testComponent.datepicker.open();
@@ -231,11 +241,9 @@ describe('MatDatepicker', () => {
fixture.detectChanges();
}
fixture.whenStable().then(() => {
expect(selectedChangedSpy.calls.count()).toEqual(1);
expect(document.querySelector('mat-dialog-container')).toBeNull();
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 2));
});
expect(selectedChangedSpy.calls.count()).toEqual(1);
expect(document.querySelector('mat-dialog-container')).toBeNull();
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 2));
});
it('startAt should fallback to input value', () => {
@@ -479,7 +487,7 @@ describe('MatDatepicker', () => {
expect(inputEl.classList).toContain('ng-touched');
});
it('should mark input touched on calendar selection', () => {
it('should mark input touched on calendar selection', async(() => {
let inputEl = fixture.debugElement.query(By.css('input')).nativeElement;
expect(inputEl.classList).toContain('ng-untouched');
@@ -492,7 +500,7 @@ describe('MatDatepicker', () => {
expect(inputEl.classList).toContain('ng-touched');
});
});
}));
});
describe('datepicker with formControl', () => {
@@ -702,7 +710,7 @@ describe('MatDatepicker', () => {
expect(testComponent.datepicker._maxDate).toEqual(new Date(2020, JAN, 1));
});
it('should mark invalid when value is before min', () => {
it('should mark invalid when value is before min', async(() => {
testComponent.date = new Date(2009, DEC, 31);
fixture.detectChanges();
@@ -712,9 +720,9 @@ describe('MatDatepicker', () => {
expect(fixture.debugElement.query(By.css('input')).nativeElement.classList)
.toContain('ng-invalid');
});
});
}));
it('should mark invalid when value is after max', () => {
it('should mark invalid when value is after max', async(() => {
testComponent.date = new Date(2020, JAN, 2);
fixture.detectChanges();
@@ -724,9 +732,9 @@ describe('MatDatepicker', () => {
expect(fixture.debugElement.query(By.css('input')).nativeElement.classList)
.toContain('ng-invalid');
});
});
}));
it('should not mark invalid when value equals min', () => {
it('should not mark invalid when value equals min', async(() => {
testComponent.date = testComponent.datepicker._minDate;
fixture.detectChanges();
@@ -736,9 +744,9 @@ describe('MatDatepicker', () => {
expect(fixture.debugElement.query(By.css('input')).nativeElement.classList)
.not.toContain('ng-invalid');
});
});
}));
it('should not mark invalid when value equals max', () => {
it('should not mark invalid when value equals max', async(() => {
testComponent.date = testComponent.datepicker._maxDate;
fixture.detectChanges();
@@ -748,9 +756,9 @@ describe('MatDatepicker', () => {
expect(fixture.debugElement.query(By.css('input')).nativeElement.classList)
.not.toContain('ng-invalid');
});
});
}));
it('should not mark invalid when value is between min and max', () => {
it('should not mark invalid when value is between min and max', async(() => {
testComponent.date = new Date(2010, JAN, 2);
fixture.detectChanges();
@@ -760,7 +768,7 @@ describe('MatDatepicker', () => {
expect(fixture.debugElement.query(By.css('input')).nativeElement.classList)
.not.toContain('ng-invalid');
});
});
}));
});
describe('datepicker with filter and validation', () => {
@@ -1078,17 +1086,27 @@ describe('MatDatepicker', () => {
input = fixture.nativeElement.querySelector('input') as HTMLInputElement;
}));
it('should have the correct input value even when inverted date format', () => {
let selected = new Date(2017, SEP, 1);
it('should have the correct input value even when inverted date format', async(() => {
if (typeof Intl === 'undefined') {
// Skip this test if the internationalization API is not supported in the current
// browser. Browsers like Safari 9 do not support the "Intl" API.
return;
}
const selected = new Date(2017, SEP, 1);
testComponent.date = selected;
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(input.value).toBe('01.09.2017');
// Normally the proper date format would 01.09.2017, but some browsers seem format the
// date without the leading zero. (e.g. 1.9.2017).
expect(input.value).toMatch(/0?1\.0?9\.2017/);
expect(testComponent.datepickerInput.value).toBe(selected);
});
});
}));
});
});
@@ -1096,10 +1114,11 @@ describe('MatDatepicker', () => {
@Component({
template: `
<input [matDatepicker]="d" [value]="date">
<mat-datepicker #d [touchUi]="touch" [disabled]="disabled"></mat-datepicker>
<mat-datepicker #d [touchUi]="touch" [disabled]="disabled" [opened]="opened"></mat-datepicker>
`,
})
class StandardDatepicker {
opened = false;
touch = false;
disabled = false;
date: Date | null = new Date(2020, JAN, 1);
+8 -5
View File
@@ -186,7 +186,10 @@ export class MatDatepicker<D> implements OnDestroy {
@Output('closed') closedStream: EventEmitter<void> = new EventEmitter<void>();
/** Whether the calendar is open. */
opened = false;
@Input()
get opened(): boolean { return this._opened; }
set opened(shouldOpen: boolean) { shouldOpen ? this.open() : this.close(); }
private _opened = false;
/** The id for the datepicker calendar. */
id = `mat-datepicker-${datepickerUid++}`;
@@ -277,7 +280,7 @@ export class MatDatepicker<D> implements OnDestroy {
/** Open the calendar. */
open(): void {
if (this.opened || this.disabled) {
if (this._opened || this.disabled) {
return;
}
if (!this._datepickerInput) {
@@ -288,13 +291,13 @@ export class MatDatepicker<D> implements OnDestroy {
}
this.touchUi ? this._openAsDialog() : this._openAsPopup();
this.opened = true;
this._opened = true;
this.openedStream.emit();
}
/** Close the calendar. */
close(): void {
if (!this.opened) {
if (!this._opened) {
return;
}
if (this._popupRef && this._popupRef.hasAttached()) {
@@ -314,7 +317,7 @@ export class MatDatepicker<D> implements OnDestroy {
this._focusedElementBeforeOpen = null;
}
this.opened = false;
this._opened = false;
this.closedStream.emit();
}