diff --git a/src/lib/autocomplete/autocomplete-trigger.ts b/src/lib/autocomplete/autocomplete-trigger.ts index 4ecefc833b50..c942146da052 100644 --- a/src/lib/autocomplete/autocomplete-trigger.ts +++ b/src/lib/autocomplete/autocomplete-trigger.ts @@ -186,9 +186,13 @@ export class MdAutocompleteTrigger implements ControlValueAccessor, OnDestroy { private get _outsideClickStream(): Observable { if (this._document) { return Observable.fromEvent(this._document, 'click').filter((event: MouseEvent) => { - let clickTarget = event.target as HTMLElement; + const clickTarget = event.target as HTMLElement; + const inputContainer = this._inputContainer ? + this._inputContainer._elementRef.nativeElement : null; + return this._panelOpen && - !this._inputContainer._elementRef.nativeElement.contains(clickTarget) && + clickTarget !== this._element.nativeElement && + (!inputContainer || !inputContainer.contains(clickTarget)) && !this._overlayRef.overlayElement.contains(clickTarget); }); } diff --git a/src/lib/autocomplete/autocomplete.spec.ts b/src/lib/autocomplete/autocomplete.spec.ts index 7336516b6c55..93b7b13aa40b 100644 --- a/src/lib/autocomplete/autocomplete.spec.ts +++ b/src/lib/autocomplete/autocomplete.spec.ts @@ -48,7 +48,8 @@ describe('MdAutocomplete', () => { AutocompleteWithoutForms, NgIfAutocomplete, AutocompleteWithNgModel, - AutocompleteWithOnPushDelay + AutocompleteWithOnPushDelay, + AutocompleteWithNativeInput ], providers: [ {provide: OverlayContainer, useFactory: () => { @@ -1065,6 +1066,24 @@ describe('MdAutocomplete', () => { })); }); + describe('without mdInput', () => { + let fixture: ComponentFixture; + + beforeEach(() => { + fixture = TestBed.createComponent(AutocompleteWithNativeInput); + fixture.detectChanges(); + }); + + it('should not throw when clicking outside', async(() => { + dispatchFakeEvent(fixture.debugElement.query(By.css('input')).nativeElement, 'focus'); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + expect(() => dispatchFakeEvent(document, 'click')).not.toThrow(); + }); + })); + }); + describe('misc', () => { it('should allow basic use without any forms directives', () => { @@ -1373,6 +1392,33 @@ class AutocompleteWithOnPushDelay implements OnInit { } } +@Component({ + template: ` + + + + + {{option}} + + + ` +}) +class AutocompleteWithNativeInput { + optionCtrl = new FormControl(); + filteredOptions: Observable; + options = ['En', 'To', 'Tre', 'Fire', 'Fem']; + + @ViewChild(MdAutocompleteTrigger) trigger: MdAutocompleteTrigger; + @ViewChildren(MdOption) mdOptions: QueryList; + + constructor() { + this.filteredOptions = this.optionCtrl.valueChanges.startWith(null).map((val) => { + return val ? this.options.filter(option => new RegExp(val, 'gi').test(option)) + : this.options.slice(); + }); + } +} + /** This is a mock keyboard event to test keyboard events in the autocomplete. */ class MockKeyboardEvent {