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' ;
2
5
import { Overlay , OverlayRef , OverlayState , TemplatePortal } from '../core' ;
3
6
import { MdAutocomplete } from './autocomplete' ;
4
7
import { PositionStrategy } from '../core/overlay/position/position-strategy' ;
5
8
import { Observable } from 'rxjs/Observable' ;
6
- import { Subscription } from 'rxjs/Subscription ' ;
9
+ import { MdOptionSelectEvent } from '../core/option/option ' ;
7
10
import 'rxjs/add/observable/merge' ;
11
+ import 'rxjs/add/operator/startWith' ;
12
+ import 'rxjs/add/operator/switchMap' ;
8
13
9
14
/** The panel needs a slight y-offset to ensure the input underline displays. */
10
15
export const MD_AUTOCOMPLETE_PANEL_OFFSET = 6 ;
@@ -20,14 +25,12 @@ export class MdAutocompleteTrigger implements OnDestroy {
20
25
private _portal : TemplatePortal ;
21
26
private _panelOpen : boolean = false ;
22
27
23
- /** The subscription to events that close the autocomplete panel. */
24
- private _closingActionsSubscription : Subscription ;
25
-
26
28
/* The autocomplete panel to be attached to this trigger. */
27
29
@Input ( 'mdAutocomplete' ) autocomplete : MdAutocomplete ;
28
30
29
31
constructor ( private _element : ElementRef , private _overlay : Overlay ,
30
- private _viewContainerRef : ViewContainerRef ) { }
32
+ private _viewContainerRef : ViewContainerRef ,
33
+ @Optional ( ) private _controlDir : NgControl ) { }
31
34
32
35
ngOnDestroy ( ) { this . _destroyPanel ( ) ; }
33
36
@@ -44,8 +47,7 @@ export class MdAutocompleteTrigger implements OnDestroy {
44
47
45
48
if ( ! this . _overlayRef . hasAttached ( ) ) {
46
49
this . _overlayRef . attach ( this . _portal ) ;
47
- this . _closingActionsSubscription =
48
- this . panelClosingActions . subscribe ( ( ) => this . closePanel ( ) ) ;
50
+ this . _subscribeToClosingActions ( ) ;
49
51
}
50
52
51
53
this . _panelOpen = true ;
@@ -57,7 +59,6 @@ export class MdAutocompleteTrigger implements OnDestroy {
57
59
this . _overlayRef . detach ( ) ;
58
60
}
59
61
60
- this . _closingActionsSubscription . unsubscribe ( ) ;
61
62
this . _panelOpen = false ;
62
63
}
63
64
@@ -75,6 +76,25 @@ export class MdAutocompleteTrigger implements OnDestroy {
75
76
return this . autocomplete . options . map ( option => option . onSelect ) ;
76
77
}
77
78
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
+ // Every time the option list changes...
86
+ this . autocomplete . options . changes
87
+ // and also at initialization, before there are any option changes...
88
+ . startWith ( null )
89
+ // create a new stream of panelClosingActions, replacing any previous streams
90
+ // that were created, and flatten it so our stream only emits closing events...
91
+ . switchMap ( ( ) => this . panelClosingActions )
92
+ // when the first closing event occurs...
93
+ . first ( )
94
+ // set the value, close the panel, and complete.
95
+ . subscribe ( event => this . _setValueAndClose ( event ) ) ;
96
+ }
97
+
78
98
/** Destroys the autocomplete suggestion panel. */
79
99
private _destroyPanel ( ) : void {
80
100
if ( this . _overlayRef ) {
@@ -84,6 +104,22 @@ export class MdAutocompleteTrigger implements OnDestroy {
84
104
}
85
105
}
86
106
107
+ /**
108
+ * This method closes the panel, and if a value is specified, also sets the associated
109
+ * control to that value. It will also mark the control as dirty if this interaction
110
+ * stemmed from the user.
111
+ */
112
+ private _setValueAndClose ( event : MdOptionSelectEvent | null ) : void {
113
+ if ( event ) {
114
+ this . _controlDir . control . setValue ( event . source . value ) ;
115
+ if ( event . isUserInput ) {
116
+ this . _controlDir . control . markAsDirty ( ) ;
117
+ }
118
+ }
119
+
120
+ this . closePanel ( ) ;
121
+ }
122
+
87
123
private _createOverlay ( ) : void {
88
124
this . _portal = new TemplatePortal ( this . autocomplete . template , this . _viewContainerRef ) ;
89
125
this . _overlayRef = this . _overlay . create ( this . _getOverlayConfig ( ) ) ;
0 commit comments