diff --git a/components/select/nz-select.component.ts b/components/select/nz-select.component.ts index bb23d969d77..4a0775d4081 100644 --- a/components/select/nz-select.component.ts +++ b/components/select/nz-select.component.ts @@ -5,6 +5,7 @@ import { transition, trigger } from '@angular/animations'; +import { DOWN_ARROW, SPACE, TAB } from '@angular/cdk/keycodes'; import { CdkConnectedOverlay, CdkOverlayOrigin, ConnectedOverlayPositionChange } from '@angular/cdk/overlay'; import { forwardRef, @@ -151,7 +152,7 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterVie @Input() nzDropdownStyle: { [ key: string ]: string; }; @Input() nzNotFoundContent: string; /** https://github.com/angular/angular/pull/13349/files **/ - // tslint:disable-next-line:no-any + // tslint:disable-next-line:no-any @Input() compareWith = (o1: any, o2: any) => o1 === o2; @Input() @@ -257,6 +258,27 @@ export class NzSelectComponent implements ControlValueAccessor, OnInit, AfterVie } } + @HostListener('keydown', [ '$event' ]) + private _handleKeydown(event: KeyboardEvent): void { + if (this._disabled) { return; } + + const keyCode = event.keyCode; + + if (!this._open) { + if (keyCode === SPACE || keyCode === DOWN_ARROW) { + this.nzOpen = true; + this.nzOpenChange.emit(this.nzOpen); + event.preventDefault(); + } + } else { + if (keyCode === SPACE || keyCode === TAB) { + this.nzOpen = false; + this.nzOpenChange.emit(this.nzOpen); + event.preventDefault(); + } + } + } + updateAutoFocus(): void { if (this.isInit && this.nzSelectTopControlComponent.inputElement) { if (this.nzAutoFocus) { diff --git a/components/select/nz-select.spec.ts b/components/select/nz-select.spec.ts index a360a9a8348..c909118bb26 100644 --- a/components/select/nz-select.spec.ts +++ b/components/select/nz-select.spec.ts @@ -1,3 +1,4 @@ +import { DOWN_ARROW, SPACE, TAB } from '@angular/cdk/keycodes'; import { Component, ViewChild } from '@angular/core'; import { async, fakeAsync, flush, inject, tick, TestBed } from '@angular/core/testing'; import { FormsModule, FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; @@ -15,7 +16,7 @@ describe('nz-select component', () => { let overlayContainerElement: HTMLElement; beforeEach(async(() => { TestBed.configureTestingModule({ - imports : [ NzSelectModule, NoopAnimationsModule, FormsModule, ReactiveFormsModule ], + imports: [ NzSelectModule, NoopAnimationsModule, FormsModule, ReactiveFormsModule ], declarations: [ NzTestSelectDefaultComponent, NzTestSelectTagsComponent, NzTestSelectFormComponent ] }); TestBed.compileComponents(); @@ -193,17 +194,47 @@ describe('nz-select component', () => { expect(testComponent.onSearch).toHaveBeenCalledTimes(1); }); it('should blur after user hits enter key in single mode', () => { - const spy = spyOn(testComponent.nzSelectComponent, 'blur'); - testComponent.showSearch = true; - select.nativeElement.click(); - fixture.detectChanges(); - dispatchKeyboardEvent(select.nativeElement.querySelector('.ant-select-selection'), 'keydown', 40); - fixture.detectChanges(); - expect(spy).not.toHaveBeenCalled(); - dispatchKeyboardEvent(select.nativeElement.querySelector('.ant-select-selection'), 'keydown', 13); - fixture.detectChanges(); - expect(spy).toHaveBeenCalled(); + const spy = spyOn(testComponent.nzSelectComponent, 'blur'); + testComponent.showSearch = true; + select.nativeElement.click(); + fixture.detectChanges(); + dispatchKeyboardEvent(select.nativeElement.querySelector('.ant-select-selection'), 'keydown', 40); + fixture.detectChanges(); + expect(spy).not.toHaveBeenCalled(); + dispatchKeyboardEvent(select.nativeElement.querySelector('.ant-select-selection'), 'keydown', 13); + fixture.detectChanges(); + expect(spy).toHaveBeenCalled(); }); + it('should support keydown events to open and close select panel', fakeAsync(() => { + fixture.detectChanges(); + dispatchKeyboardEvent(select.nativeElement.querySelector('.ant-select-selection'), 'keydown', SPACE); + fixture.detectChanges(); + flush(); + fixture.detectChanges(); + expect(testComponent.open).toBe(true); + dispatchKeyboardEvent(select.nativeElement.querySelector('.ant-select-selection'), 'keydown', SPACE); + fixture.detectChanges(); + flush(); + fixture.detectChanges(); + expect(testComponent.open).toBe(false); + dispatchKeyboardEvent(select.nativeElement.querySelector('.ant-select-selection'), 'keydown', DOWN_ARROW); + fixture.detectChanges(); + flush(); + fixture.detectChanges(); + expect(testComponent.open).toBe(true); + dispatchKeyboardEvent(select.nativeElement.querySelector('.ant-select-selection'), 'keydown', TAB); + fixture.detectChanges(); + flush(); + fixture.detectChanges(); + expect(testComponent.open).toBe(false); + testComponent.disabled = true; + fixture.detectChanges(); + dispatchKeyboardEvent(select.nativeElement.querySelector('.ant-select-selection'), 'keydown', TAB); + fixture.detectChanges(); + flush(); + fixture.detectChanges(); + expect(testComponent.open).toBe(false); + })); }); describe('tags', () => { let fixture;