1- import { Directive , ElementRef , Input , ViewContainerRef , OnDestroy } from '@angular/core' ;
1+ import {
2+ Directive , ElementRef , Input , ViewContainerRef , Optional , OnDestroy
3+ } from '@angular/core' ;
4+ import { NgControl } from '@angular/forms' ;
25import { Overlay , OverlayRef , OverlayState , TemplatePortal } from '../core' ;
36import { MdAutocomplete } from './autocomplete' ;
47import { PositionStrategy } from '../core/overlay/position/position-strategy' ;
58import { Observable } from 'rxjs/Observable' ;
69import { Subscription } from 'rxjs/Subscription' ;
10+ import { MdOptionSelectEvent } from '../core/option/option' ;
711import 'rxjs/add/observable/merge' ;
12+ import 'rxjs/add/operator/startWith' ;
13+ import 'rxjs/add/operator/switchMap' ;
814
915/** The panel needs a slight y-offset to ensure the input underline displays. */
1016export const MD_AUTOCOMPLETE_PANEL_OFFSET = 6 ;
@@ -20,14 +26,12 @@ export class MdAutocompleteTrigger implements OnDestroy {
2026 private _portal : TemplatePortal ;
2127 private _panelOpen : boolean = false ;
2228
23- /** The subscription to events that close the autocomplete panel. */
24- private _closingActionsSubscription : Subscription ;
25-
2629 /* The autocomplete panel to be attached to this trigger. */
2730 @Input ( 'mdAutocomplete' ) autocomplete : MdAutocomplete ;
2831
2932 constructor ( private _element : ElementRef , private _overlay : Overlay ,
30- private _viewContainerRef : ViewContainerRef ) { }
33+ private _viewContainerRef : ViewContainerRef ,
34+ @Optional ( ) private _controlDir : NgControl ) { }
3135
3236 ngOnDestroy ( ) { this . _destroyPanel ( ) ; }
3337
@@ -44,8 +48,7 @@ export class MdAutocompleteTrigger implements OnDestroy {
4448
4549 if ( ! this . _overlayRef . hasAttached ( ) ) {
4650 this . _overlayRef . attach ( this . _portal ) ;
47- this . _closingActionsSubscription =
48- this . panelClosingActions . subscribe ( ( ) => this . closePanel ( ) ) ;
51+ this . _subscribeToClosingActions ( ) ;
4952 }
5053
5154 this . _panelOpen = true ;
@@ -57,7 +60,6 @@ export class MdAutocompleteTrigger implements OnDestroy {
5760 this . _overlayRef . detach ( ) ;
5861 }
5962
60- this . _closingActionsSubscription . unsubscribe ( ) ;
6163 this . _panelOpen = false ;
6264 }
6365
@@ -75,6 +77,19 @@ export class MdAutocompleteTrigger implements OnDestroy {
7577 return this . autocomplete . options . map ( option => option . onSelect ) ;
7678 }
7779
80+
81+ /**
82+ * This method listens to a stream of panel closing actions and resets the
83+ * stream every time the option list changes.
84+ */
85+ private _subscribeToClosingActions ( ) : void {
86+ this . autocomplete . options . changes
87+ . startWith ( null )
88+ . switchMap ( ( ) => this . panelClosingActions )
89+ . first ( )
90+ . subscribe ( event => this . _setValueAndClose ( event ) ) ;
91+ }
92+
7893 /** Destroys the autocomplete suggestion panel. */
7994 private _destroyPanel ( ) : void {
8095 if ( this . _overlayRef ) {
@@ -84,6 +99,23 @@ export class MdAutocompleteTrigger implements OnDestroy {
8499 }
85100 }
86101
102+ /**
103+ * This method closes the panel, and if a value is specified, also sets the associated
104+ * control to that value. It will also mark the control as dirty if this interaction
105+ * stemmed from the user.
106+ */
107+ private _setValueAndClose ( event : MdOptionSelectEvent | null ) : void {
108+ if ( event ) {
109+ // TODO(kara): revisit animation once floating placeholder is toggle-able
110+ this . _controlDir . control . setValue ( event . source . value ) ;
111+ if ( event . isUserInput ) {
112+ this . _controlDir . control . markAsDirty ( ) ;
113+ }
114+ }
115+
116+ this . closePanel ( ) ;
117+ }
118+
87119 private _createOverlay ( ) : void {
88120 this . _portal = new TemplatePortal ( this . autocomplete . template , this . _viewContainerRef ) ;
89121 this . _overlayRef = this . _overlay . create ( this . _getOverlayConfig ( ) ) ;
0 commit comments