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 ;
@@ -20,12 +24,13 @@ export class MdAutocompleteTrigger implements OnDestroy {
2024 private _portal : TemplatePortal ;
2125 private _panelOpen : boolean = false ;
2226 private _closeWatcher : Subscription ;
27+ private _optionWatcher : Subscription ;
2328
2429 /* The autocomplete panel to be attached to this trigger. */
2530 @Input ( 'mdAutocomplete' ) autocomplete : MdAutocomplete ;
2631
2732 constructor ( private _element : ElementRef , private _overlay : Overlay ,
28- private _vcr : ViewContainerRef ) { }
33+ private _vcr : ViewContainerRef , @ Optional ( ) private _controlDir : NgControl ) { }
2934
3035 ngOnDestroy ( ) { this . destroyPanel ( ) ; }
3136
@@ -43,6 +48,8 @@ export class MdAutocompleteTrigger implements OnDestroy {
4348 if ( ! this . _overlayRef . hasAttached ( ) ) {
4449 this . _overlayRef . attach ( this . _portal ) ;
4550 this . _watchForClose ( ) ;
51+ this . _optionWatcher =
52+ this . autocomplete . options . changes . subscribe ( ( ) => this . _watchForClose ( ) ) ;
4653 }
4754
4855 this . _panelOpen = true ;
@@ -54,6 +61,7 @@ export class MdAutocompleteTrigger implements OnDestroy {
5461 this . _overlayRef . detach ( ) ;
5562 }
5663
64+ this . _optionWatcher . unsubscribe ( ) ;
5765 this . _closeWatcher . unsubscribe ( ) ;
5866 this . _panelOpen = false ;
5967 }
@@ -71,10 +79,13 @@ export class MdAutocompleteTrigger implements OnDestroy {
7179 * This method will close the panel if it receives a selection event from any of the options
7280 * or a click on the backdrop.
7381 */
74- private _watchForClose ( ) {
82+ private _watchForClose ( ) : void {
7583 // TODO(kara): add tab event watcher when adding keyboard events
84+ if ( this . _closeWatcher ) {
85+ this . _closeWatcher . unsubscribe ( ) ;
86+ }
7687 this . _closeWatcher = Observable . merge ( ...this . _getOptionObs ( ) , this . _overlayRef . backdropClick ( ) )
77- . subscribe ( ( ) => this . closePanel ( ) ) ;
88+ . subscribe ( ( event ) => this . _setValueAndClose ( event ) ) ;
7889 }
7990
8091 /**
@@ -86,6 +97,23 @@ export class MdAutocompleteTrigger implements OnDestroy {
8697 return this . autocomplete . options . map ( ( option ) => option . onSelect ) ;
8798 }
8899
100+ /**
101+ * This method closes the panel, and if a value is specified, also sets the associated
102+ * control to that value. It will also mark the control as dirty if this interaction
103+ * stemmed from the user.
104+ */
105+ private _setValueAndClose ( event : MdOptionSelectEvent | null ) : void {
106+ if ( event ) {
107+ // TODO(kara): revisit animation once floating placeholder is toggle-able
108+ this . _controlDir . control . setValue ( event . source . viewValue ) ;
109+ if ( event . isUserInput ) {
110+ this . _controlDir . control . markAsDirty ( ) ;
111+ }
112+ }
113+
114+ this . closePanel ( ) ;
115+ }
116+
89117 private _createOverlay ( ) : void {
90118 this . _portal = new TemplatePortal ( this . autocomplete . template , this . _vcr ) ;
91119 this . _overlayRef = this . _overlay . create ( this . _getOverlayConfig ( ) ) ;
0 commit comments