1
1
import {
2
2
Directive , ElementRef , Input , ViewContainerRef , Optional , OnDestroy
3
3
} from '@angular/core' ;
4
+ import { NgControl } from '@angular/forms' ;
4
5
import { Overlay , OverlayRef , OverlayState , TemplatePortal } from '../core' ;
5
6
import { MdAutocomplete } from './autocomplete' ;
6
7
import { PositionStrategy } from '../core/overlay/position/position-strategy' ;
7
8
import { Observable } from 'rxjs/Observable' ;
8
- import { Subscription } from 'rxjs/Subscription ' ;
9
+ import { MdOptionSelectEvent } from '../core/option/option ' ;
9
10
import 'rxjs/add/observable/merge' ;
10
11
import { Dir } from '../core/rtl/dir' ;
12
+ import 'rxjs/add/operator/startWith' ;
13
+ import 'rxjs/add/operator/switchMap' ;
14
+
11
15
12
16
/** The panel needs a slight y-offset to ensure the input underline displays. */
13
17
export const MD_AUTOCOMPLETE_PANEL_OFFSET = 6 ;
@@ -23,14 +27,12 @@ export class MdAutocompleteTrigger implements OnDestroy {
23
27
private _portal : TemplatePortal ;
24
28
private _panelOpen : boolean = false ;
25
29
26
- /** The subscription to events that close the autocomplete panel. */
27
- private _closingActionsSubscription : Subscription ;
28
-
29
30
/* The autocomplete panel to be attached to this trigger. */
30
31
@Input ( 'mdAutocomplete' ) autocomplete : MdAutocomplete ;
31
32
32
33
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 ) { }
34
36
35
37
ngOnDestroy ( ) { this . _destroyPanel ( ) ; }
36
38
@@ -47,8 +49,7 @@ export class MdAutocompleteTrigger implements OnDestroy {
47
49
48
50
if ( ! this . _overlayRef . hasAttached ( ) ) {
49
51
this . _overlayRef . attach ( this . _portal ) ;
50
- this . _closingActionsSubscription =
51
- this . panelClosingActions . subscribe ( ( ) => this . closePanel ( ) ) ;
52
+ this . _subscribeToClosingActions ( ) ;
52
53
}
53
54
54
55
this . _panelOpen = true ;
@@ -60,7 +61,6 @@ export class MdAutocompleteTrigger implements OnDestroy {
60
61
this . _overlayRef . detach ( ) ;
61
62
}
62
63
63
- this . _closingActionsSubscription . unsubscribe ( ) ;
64
64
this . _panelOpen = false ;
65
65
}
66
66
@@ -78,6 +78,25 @@ export class MdAutocompleteTrigger implements OnDestroy {
78
78
return this . autocomplete . options . map ( option => option . onSelect ) ;
79
79
}
80
80
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
+
81
100
/** Destroys the autocomplete suggestion panel. */
82
101
private _destroyPanel ( ) : void {
83
102
if ( this . _overlayRef ) {
@@ -87,6 +106,22 @@ export class MdAutocompleteTrigger implements OnDestroy {
87
106
}
88
107
}
89
108
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
+
90
125
private _createOverlay ( ) : void {
91
126
this . _portal = new TemplatePortal ( this . autocomplete . template , this . _viewContainerRef ) ;
92
127
this . _overlayRef = this . _overlay . create ( this . _getOverlayConfig ( ) ) ;
0 commit comments