11import {
22 Directive , ElementRef , Input , ViewContainerRef , Optional , OnDestroy
33} from '@angular/core' ;
4+ import { NgControl } from '@angular/forms' ;
45import { Overlay , OverlayRef , OverlayState , TemplatePortal } from '../core' ;
56import { MdAutocomplete } from './autocomplete' ;
67import { PositionStrategy } from '../core/overlay/position/position-strategy' ;
78import { Observable } from 'rxjs/Observable' ;
8- import { Subscription } from 'rxjs/Subscription ' ;
9+ import { MdOptionSelectEvent } from '../core/option/option ' ;
910import 'rxjs/add/observable/merge' ;
1011import { Dir } from '../core/rtl/dir' ;
12+ import 'rxjs/add/operator/startWith' ;
13+ import 'rxjs/add/operator/switchMap' ;
14+
1115
1216/** The panel needs a slight y-offset to ensure the input underline displays. */
1317export const MD_AUTOCOMPLETE_PANEL_OFFSET = 6 ;
@@ -23,14 +27,12 @@ export class MdAutocompleteTrigger implements OnDestroy {
2327 private _portal : TemplatePortal ;
2428 private _panelOpen : boolean = false ;
2529
26- /** The subscription to events that close the autocomplete panel. */
27- private _closingActionsSubscription : Subscription ;
28-
2930 /* The autocomplete panel to be attached to this trigger. */
3031 @Input ( 'mdAutocomplete' ) autocomplete : MdAutocomplete ;
3132
3233 constructor ( private _element : ElementRef , private _overlay : Overlay ,
33- private _viewContainerRef : ViewContainerRef , @Optional ( ) private _dir : Dir ) { }
34+ private _viewContainerRef : ViewContainerRef ,
35+ @Optional ( ) private _controlDir : NgControl , @Optional ( ) private _dir : Dir ) { }
3436
3537 ngOnDestroy ( ) { this . _destroyPanel ( ) ; }
3638
@@ -47,8 +49,7 @@ export class MdAutocompleteTrigger implements OnDestroy {
4749
4850 if ( ! this . _overlayRef . hasAttached ( ) ) {
4951 this . _overlayRef . attach ( this . _portal ) ;
50- this . _closingActionsSubscription =
51- this . panelClosingActions . subscribe ( ( ) => this . closePanel ( ) ) ;
52+ this . _subscribeToClosingActions ( ) ;
5253 }
5354
5455 this . _panelOpen = true ;
@@ -60,7 +61,6 @@ export class MdAutocompleteTrigger implements OnDestroy {
6061 this . _overlayRef . detach ( ) ;
6162 }
6263
63- this . _closingActionsSubscription . unsubscribe ( ) ;
6464 this . _panelOpen = false ;
6565 }
6666
@@ -78,6 +78,25 @@ export class MdAutocompleteTrigger implements OnDestroy {
7878 return this . autocomplete . options . map ( option => option . onSelect ) ;
7979 }
8080
81+
82+ /**
83+ * This method listens to a stream of panel closing actions and resets the
84+ * stream every time the option list changes.
85+ */
86+ private _subscribeToClosingActions ( ) : void {
87+ // Every time the option list changes...
88+ this . autocomplete . options . changes
89+ // and also at initialization, before there are any option changes...
90+ . startWith ( null )
91+ // create a new stream of panelClosingActions, replacing any previous streams
92+ // that were created, and flatten it so our stream only emits closing events...
93+ . switchMap ( ( ) => this . panelClosingActions )
94+ // when the first closing event occurs...
95+ . first ( )
96+ // set the value, close the panel, and complete.
97+ . subscribe ( event => this . _setValueAndClose ( event ) ) ;
98+ }
99+
81100 /** Destroys the autocomplete suggestion panel. */
82101 private _destroyPanel ( ) : void {
83102 if ( this . _overlayRef ) {
@@ -87,6 +106,22 @@ export class MdAutocompleteTrigger implements OnDestroy {
87106 }
88107 }
89108
109+ /**
110+ * This method closes the panel, and if a value is specified, also sets the associated
111+ * control to that value. It will also mark the control as dirty if this interaction
112+ * stemmed from the user.
113+ */
114+ private _setValueAndClose ( event : MdOptionSelectEvent | null ) : void {
115+ if ( event ) {
116+ this . _controlDir . control . setValue ( event . source . value ) ;
117+ if ( event . isUserInput ) {
118+ this . _controlDir . control . markAsDirty ( ) ;
119+ }
120+ }
121+
122+ this . closePanel ( ) ;
123+ }
124+
90125 private _createOverlay ( ) : void {
91126 this . _portal = new TemplatePortal ( this . autocomplete . template , this . _viewContainerRef ) ;
92127 this . _overlayRef = this . _overlay . create ( this . _getOverlayConfig ( ) ) ;
0 commit comments