mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(datepicker): add opened input binding (#8098)
* Adds support for the `opened` input binding. Closes #8094
This commit is contained in:
committed by
tinayuangao
parent
9e35bf0e21
commit
2b9bc5769a
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user