Skip to content

Commit

Permalink
fix(datepicker): don't close on Escape if autoClose is false
Browse files Browse the repository at this point in the history
Fixes #2704
Closes #2713
  • Loading branch information
maxokorokov committed Sep 20, 2018
1 parent 5dd4e1e commit 83b49c2
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 24 deletions.
26 changes: 24 additions & 2 deletions src/datepicker/datepicker-input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,13 @@ describe('NgbInputDatepicker', () => {
outsideButton.click();
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('ngb-datepicker')).not.toBeNull();

// escape
dispatchKeyUpEvent(Key.Escape);
expect(fixture.nativeElement.querySelector('ngb-datepicker')).not.toBeNull();
});

it(`should close datepicker only on date selection if 'autoClose' set to 'inside'`, () => {
it(`should close datepicker only on date selection and Escape if 'autoClose' set to 'inside'`, () => {
const fixture = createTestCmpt(`
<input ngbDatepicker #d="ngbDatepicker" autoClose="inside">
<button (click)="open(d)">Open</button>
Expand All @@ -195,9 +199,18 @@ describe('NgbInputDatepicker', () => {
dp.select.emit();
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('ngb-datepicker')).toBeNull();

// open
button.click();
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('ngb-datepicker')).not.toBeNull();

// escape
dispatchKeyUpEvent(Key.Escape);
expect(fixture.nativeElement.querySelector('ngb-datepicker')).toBeNull();
});

it(`should close datepicker only on outside click if 'autoClose' set to 'outside'`, fakeAsync(() => {
it(`should close datepicker only on outside click and Escape if 'autoClose' set to 'outside'`, fakeAsync(() => {
const fixture = createTestCmpt(`
<input ngbDatepicker #d="ngbDatepicker" autoClose="outside">
<button (click)="open(d)">Open</button>
Expand All @@ -222,6 +235,15 @@ describe('NgbInputDatepicker', () => {
outsideButton.click();
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('ngb-datepicker')).toBeNull();

// open
button.click();
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('ngb-datepicker')).not.toBeNull();

// escape
dispatchKeyUpEvent(Key.Escape);
expect(fixture.nativeElement.querySelector('ngb-datepicker')).toBeNull();
}));
});

Expand Down
46 changes: 24 additions & 22 deletions src/datepicker/datepicker-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,28 +286,30 @@ export class NgbInputDatepicker implements OnChanges,
this._cRef.instance.focus();

// closing on ESC and outside clicks
this._ngZone.runOutsideAngular(() => {

const escapes$ = fromEvent<KeyboardEvent>(this._document, 'keyup')
.pipe(takeUntil(this._closed$), filter(e => e.which === Key.Escape));

let outsideClicks$;
if (this.autoClose === true || this.autoClose === 'outside') {
// we don't know how the popup was opened, so if it was opened with a click,
// we have to skip the first one to avoid closing it immediately
let isOpening = true;
requestAnimationFrame(() => isOpening = false);

outsideClicks$ =
fromEvent<MouseEvent>(this._document, 'click')
.pipe(
takeUntil(this._closed$), filter(event => !isOpening && this._shouldCloseOnOutsideClick(event)));
} else {
outsideClicks$ = NEVER;
}

race<Event>([escapes$, outsideClicks$]).subscribe(() => this._ngZone.run(() => this.close()));
});
if (this.autoClose) {
this._ngZone.runOutsideAngular(() => {

const escapes$ = fromEvent<KeyboardEvent>(this._document, 'keyup')
.pipe(takeUntil(this._closed$), filter(e => e.which === Key.Escape));

let outsideClicks$;
if (this.autoClose === true || this.autoClose === 'outside') {
// we don't know how the popup was opened, so if it was opened with a click,
// we have to skip the first one to avoid closing it immediately
let isOpening = true;
requestAnimationFrame(() => isOpening = false);

outsideClicks$ = fromEvent<MouseEvent>(this._document, 'click')
.pipe(
takeUntil(this._closed$),
filter(event => !isOpening && this._shouldCloseOnOutsideClick(event)));
} else {
outsideClicks$ = NEVER;
}

race<Event>([escapes$, outsideClicks$]).subscribe(() => this._ngZone.run(() => this.close()));
});
}
}
}

Expand Down

0 comments on commit 83b49c2

Please sign in to comment.