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' ;
710import 'rxjs/add/observable/merge' ;
11+ import { MdOptionSelectEvent } from '../core/option/option' ;
812
913/** The panel needs a slight y-offset to ensure the input underline displays. */
1014export const MD_AUTOCOMPLETE_PANEL_OFFSET = 6 ;
@@ -23,11 +27,15 @@ export class MdAutocompleteTrigger implements OnDestroy {
2327 /** The subscription to events that close the autocomplete panel. */
2428 private _closingActionsSubscription : Subscription ;
2529
30+ /** The subscription to changes in the options list. */
31+ private _optionChangesSubscription : Subscription ;
32+
2633 /* The autocomplete panel to be attached to this trigger. */
2734 @Input ( 'mdAutocomplete' ) autocomplete : MdAutocomplete ;
2835
2936 constructor ( private _element : ElementRef , private _overlay : Overlay ,
30- private _viewContainerRef : ViewContainerRef ) { }
37+ private _viewContainerRef : ViewContainerRef ,
38+ @Optional ( ) private _controlDir : NgControl ) { }
3139
3240 ngOnDestroy ( ) { this . _destroyPanel ( ) ; }
3341
@@ -44,8 +52,9 @@ export class MdAutocompleteTrigger implements OnDestroy {
4452
4553 if ( ! this . _overlayRef . hasAttached ( ) ) {
4654 this . _overlayRef . attach ( this . _portal ) ;
47- this . _closingActionsSubscription =
48- this . panelClosingActions . subscribe ( ( ) => this . closePanel ( ) ) ;
55+ this . _resetClosingActionSub ( ) ;
56+ this . _optionChangesSubscription =
57+ this . autocomplete . options . changes . subscribe ( ( ) => this . _resetClosingActionSub ( ) ) ;
4958 }
5059
5160 this . _panelOpen = true ;
@@ -58,6 +67,7 @@ export class MdAutocompleteTrigger implements OnDestroy {
5867 }
5968
6069 this . _closingActionsSubscription . unsubscribe ( ) ;
70+ this . _optionChangesSubscription . unsubscribe ( ) ;
6171 this . _panelOpen = false ;
6272 }
6373
@@ -75,6 +85,20 @@ export class MdAutocompleteTrigger implements OnDestroy {
7585 return this . autocomplete . options . map ( option => option . onSelect ) ;
7686 }
7787
88+ /**
89+ * Drops the current closing action subscription and re-creates it.
90+ * Used whenever the option list changes to ensure that new options
91+ * can be selected properly.
92+ */
93+ private _resetClosingActionSub ( ) {
94+ if ( this . _closingActionsSubscription ) {
95+ this . _closingActionsSubscription . unsubscribe ( ) ;
96+ }
97+
98+ this . _closingActionsSubscription =
99+ this . panelClosingActions . subscribe ( event => this . _setValueAndClose ( event ) ) ;
100+ }
101+
78102 /** Destroys the autocomplete suggestion panel. */
79103 private _destroyPanel ( ) : void {
80104 if ( this . _overlayRef ) {
@@ -84,6 +108,23 @@ export class MdAutocompleteTrigger implements OnDestroy {
84108 }
85109 }
86110
111+ /**
112+ * This method closes the panel, and if a value is specified, also sets the associated
113+ * control to that value. It will also mark the control as dirty if this interaction
114+ * stemmed from the user.
115+ */
116+ private _setValueAndClose ( event : MdOptionSelectEvent | null ) : void {
117+ if ( event ) {
118+ // TODO(kara): revisit animation once floating placeholder is toggle-able
119+ this . _controlDir . control . setValue ( event . source . value ) ;
120+ if ( event . isUserInput ) {
121+ this . _controlDir . control . markAsDirty ( ) ;
122+ }
123+ }
124+
125+ this . closePanel ( ) ;
126+ }
127+
87128 private _createOverlay ( ) : void {
88129 this . _portal = new TemplatePortal ( this . autocomplete . template , this . _viewContainerRef ) ;
89130 this . _overlayRef = this . _overlay . create ( this . _getOverlayConfig ( ) ) ;
0 commit comments