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' ;
6- import { Subscription } from 'rxjs/Subscription ' ;
9+ import { MdOptionSelectEvent } from '../core/option/option ' ;
710import 'rxjs/add/observable/merge' ;
11+ import 'rxjs/add/operator/startWith' ;
12+ import 'rxjs/add/operator/switchMap' ;
813
914/** The panel needs a slight y-offset to ensure the input underline displays. */
1015export const MD_AUTOCOMPLETE_PANEL_OFFSET = 6 ;
@@ -20,14 +25,12 @@ export class MdAutocompleteTrigger implements OnDestroy {
2025 private _portal : TemplatePortal ;
2126 private _panelOpen : boolean = false ;
2227
23- /** The subscription to events that close the autocomplete panel. */
24- private _closingActionsSubscription : Subscription ;
25-
2628 /* The autocomplete panel to be attached to this trigger. */
2729 @Input ( 'mdAutocomplete' ) autocomplete : MdAutocomplete ;
2830
2931 constructor ( private _element : ElementRef , private _overlay : Overlay ,
30- private _viewContainerRef : ViewContainerRef ) { }
32+ private _viewContainerRef : ViewContainerRef ,
33+ @Optional ( ) private _controlDir : NgControl ) { }
3134
3235 ngOnDestroy ( ) { this . _destroyPanel ( ) ; }
3336
@@ -44,8 +47,7 @@ export class MdAutocompleteTrigger implements OnDestroy {
4447
4548 if ( ! this . _overlayRef . hasAttached ( ) ) {
4649 this . _overlayRef . attach ( this . _portal ) ;
47- this . _closingActionsSubscription =
48- this . panelClosingActions . subscribe ( ( ) => this . closePanel ( ) ) ;
50+ this . _subscribeToClosingActions ( ) ;
4951 }
5052
5153 this . _panelOpen = true ;
@@ -57,7 +59,6 @@ export class MdAutocompleteTrigger implements OnDestroy {
5759 this . _overlayRef . detach ( ) ;
5860 }
5961
60- this . _closingActionsSubscription . unsubscribe ( ) ;
6162 this . _panelOpen = false ;
6263 }
6364
@@ -75,6 +76,19 @@ export class MdAutocompleteTrigger implements OnDestroy {
7576 return this . autocomplete . options . map ( option => option . onSelect ) ;
7677 }
7778
79+
80+ /**
81+ * This method listens to a stream of panel closing actions and resets the
82+ * stream every time the option list changes.
83+ */
84+ private _subscribeToClosingActions ( ) : void {
85+ this . autocomplete . options . changes
86+ . startWith ( null )
87+ . switchMap ( ( ) => this . panelClosingActions )
88+ . first ( )
89+ . subscribe ( event => this . _setValueAndClose ( event ) ) ;
90+ }
91+
7892 /** Destroys the autocomplete suggestion panel. */
7993 private _destroyPanel ( ) : void {
8094 if ( this . _overlayRef ) {
@@ -84,6 +98,23 @@ export class MdAutocompleteTrigger implements OnDestroy {
8498 }
8599 }
86100
101+ /**
102+ * This method closes the panel, and if a value is specified, also sets the associated
103+ * control to that value. It will also mark the control as dirty if this interaction
104+ * stemmed from the user.
105+ */
106+ private _setValueAndClose ( event : MdOptionSelectEvent | null ) : void {
107+ if ( event ) {
108+ // TODO(kara): revisit animation once floating placeholder is toggle-able
109+ this . _controlDir . control . setValue ( event . source . value ) ;
110+ if ( event . isUserInput ) {
111+ this . _controlDir . control . markAsDirty ( ) ;
112+ }
113+ }
114+
115+ this . closePanel ( ) ;
116+ }
117+
87118 private _createOverlay ( ) : void {
88119 this . _portal = new TemplatePortal ( this . autocomplete . template , this . _viewContainerRef ) ;
89120 this . _overlayRef = this . _overlay . create ( this . _getOverlayConfig ( ) ) ;
0 commit comments