mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(autocomplete): emit event when an option is selected (#4187)
Fixes #4094. Fixes #3645.
This commit is contained in:
committed by
Kara
parent
844a81c248
commit
2dd5c7c3f1
@@ -427,6 +427,7 @@ export class MdAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
|
||||
this._setTriggerValue(event.source.value);
|
||||
this._onChange(event.source.value);
|
||||
this._element.nativeElement.focus();
|
||||
this.autocomplete._emitSelectEvent(event.source);
|
||||
}
|
||||
|
||||
this.closePanel();
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
MdAutocomplete,
|
||||
MdAutocompleteModule,
|
||||
MdAutocompleteTrigger,
|
||||
MdAutocompleteSelectedEvent,
|
||||
} from './index';
|
||||
import {MdInputModule} from '../input/index';
|
||||
import {Subscription} from 'rxjs/Subscription';
|
||||
@@ -57,7 +58,8 @@ describe('MdAutocomplete', () => {
|
||||
AutocompleteWithNativeInput,
|
||||
AutocompleteWithoutPanel,
|
||||
AutocompleteWithFormsAndNonfloatingPlaceholder,
|
||||
AutocompleteWithGroups
|
||||
AutocompleteWithGroups,
|
||||
AutocompleteWithSelectEvent,
|
||||
],
|
||||
providers: [
|
||||
{provide: OverlayContainer, useFactory: () => {
|
||||
@@ -1548,6 +1550,55 @@ describe('MdAutocomplete', () => {
|
||||
expect(panel.classList).toContain(visibleClass, `Expected panel to be visible.`);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should emit an event when an option is selected', fakeAsync(() => {
|
||||
let fixture = TestBed.createComponent(AutocompleteWithSelectEvent);
|
||||
|
||||
fixture.detectChanges();
|
||||
fixture.componentInstance.trigger.openPanel();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
let options = overlayContainerElement.querySelectorAll('md-option') as NodeListOf<HTMLElement>;
|
||||
let spy = fixture.componentInstance.optionSelected;
|
||||
|
||||
options[1].click();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
|
||||
let event = spy.calls.mostRecent().args[0] as MdAutocompleteSelectedEvent;
|
||||
|
||||
expect(event.source).toBe(fixture.componentInstance.autocomplete);
|
||||
expect(event.option.value).toBe('Washington');
|
||||
}));
|
||||
|
||||
it('should emit an event when a newly-added option is selected', fakeAsync(() => {
|
||||
let fixture = TestBed.createComponent(AutocompleteWithSelectEvent);
|
||||
|
||||
fixture.detectChanges();
|
||||
fixture.componentInstance.trigger.openPanel();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.componentInstance.states.push('Puerto Rico');
|
||||
fixture.detectChanges();
|
||||
|
||||
let options = overlayContainerElement.querySelectorAll('md-option') as NodeListOf<HTMLElement>;
|
||||
let spy = fixture.componentInstance.optionSelected;
|
||||
|
||||
options[3].click();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
|
||||
let event = spy.calls.mostRecent().args[0] as MdAutocompleteSelectedEvent;
|
||||
|
||||
expect(event.source).toBe(fixture.componentInstance.autocomplete);
|
||||
expect(event.option.value).toBe('Puerto Rico');
|
||||
}));
|
||||
});
|
||||
|
||||
@Component({
|
||||
@@ -1826,3 +1877,25 @@ class AutocompleteWithGroups {
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<md-input-container>
|
||||
<input mdInput placeholder="State" [mdAutocomplete]="auto" [(ngModel)]="selectedState">
|
||||
</md-input-container>
|
||||
|
||||
<md-autocomplete #auto="mdAutocomplete" (optionSelected)="optionSelected($event)">
|
||||
<md-option *ngFor="let state of states" [value]="state">
|
||||
<span>{{ state }}</span>
|
||||
</md-option>
|
||||
</md-autocomplete>
|
||||
`
|
||||
})
|
||||
class AutocompleteWithSelectEvent {
|
||||
selectedState: string;
|
||||
states = ['New York', 'Washington', 'Oregon'];
|
||||
optionSelected = jasmine.createSpy('optionSelected callback');
|
||||
|
||||
@ViewChild(MdAutocompleteTrigger) trigger: MdAutocompleteTrigger;
|
||||
@ViewChild(MdAutocomplete) autocomplete: MdAutocomplete;
|
||||
}
|
||||
|
||||
@@ -18,16 +18,25 @@ import {
|
||||
ViewEncapsulation,
|
||||
ChangeDetectorRef,
|
||||
ChangeDetectionStrategy,
|
||||
EventEmitter,
|
||||
Output,
|
||||
} from '@angular/core';
|
||||
import {MdOption, MdOptgroup} from '../core';
|
||||
import {ActiveDescendantKeyManager} from '@angular/cdk/a11y';
|
||||
|
||||
|
||||
/**
|
||||
* Autocomplete IDs need to be unique across components, so this counter exists outside of
|
||||
* the component definition.
|
||||
*/
|
||||
let _uniqueAutocompleteIdCounter = 0;
|
||||
|
||||
/** Event object that is emitted when an autocomplete option is selected */
|
||||
export class MdAutocompleteSelectedEvent {
|
||||
constructor(public source: MdAutocomplete, public option: MdOption) { }
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'md-autocomplete, mat-autocomplete',
|
||||
@@ -63,6 +72,10 @@ export class MdAutocomplete implements AfterContentInit {
|
||||
/** Function that maps an option's control value to its display value in the trigger. */
|
||||
@Input() displayWith: ((value: any) => string) | null = null;
|
||||
|
||||
/** Event that is emitted whenever an option from the list is selected. */
|
||||
@Output() optionSelected: EventEmitter<MdAutocompleteSelectedEvent> =
|
||||
new EventEmitter<MdAutocompleteSelectedEvent>();
|
||||
|
||||
/** Unique ID to be used by autocomplete trigger's "aria-owns" property. */
|
||||
id: string = `md-autocomplete-${_uniqueAutocompleteIdCounter++}`;
|
||||
|
||||
@@ -88,13 +101,19 @@ export class MdAutocomplete implements AfterContentInit {
|
||||
}
|
||||
|
||||
/** Panel should hide itself when the option list is empty. */
|
||||
_setVisibility() {
|
||||
_setVisibility(): void {
|
||||
Promise.resolve().then(() => {
|
||||
this.showPanel = !!this.options.length;
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/** Emits the `select` event. */
|
||||
_emitSelectEvent(option: MdOption): void {
|
||||
const event = new MdAutocompleteSelectedEvent(this, option);
|
||||
this.optionSelected.emit(event);
|
||||
}
|
||||
|
||||
/** Sets a class on the panel based on whether it is visible. */
|
||||
_getClassList() {
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user