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
9
import { Subscription } from 'rxjs/Subscription' ;
7
10
import 'rxjs/add/observable/merge' ;
11
+ import { MdOptionSelectEvent } from '../core/option/option' ;
8
12
9
13
/** The panel needs a slight y-offset to ensure the input underline displays. */
10
14
export const MD_AUTOCOMPLETE_PANEL_OFFSET = 6 ;
@@ -20,12 +24,13 @@ export class MdAutocompleteTrigger implements OnDestroy {
20
24
private _portal : TemplatePortal ;
21
25
private _panelOpen : boolean = false ;
22
26
private _closeWatcher : Subscription ;
27
+ private _optionWatcher : Subscription ;
23
28
24
29
/* The autocomplete panel to be attached to this trigger. */
25
30
@Input ( 'mdAutocomplete' ) autocomplete : MdAutocomplete ;
26
31
27
32
constructor ( private _element : ElementRef , private _overlay : Overlay ,
28
- private _vcr : ViewContainerRef ) { }
33
+ private _vcr : ViewContainerRef , @ Optional ( ) private _controlDir : NgControl ) { }
29
34
30
35
ngOnDestroy ( ) { this . destroyPanel ( ) ; }
31
36
@@ -43,6 +48,8 @@ export class MdAutocompleteTrigger implements OnDestroy {
43
48
if ( ! this . _overlayRef . hasAttached ( ) ) {
44
49
this . _overlayRef . attach ( this . _portal ) ;
45
50
this . _watchForClose ( ) ;
51
+ this . _optionWatcher =
52
+ this . autocomplete . options . changes . subscribe ( ( ) => this . _watchForClose ( ) ) ;
46
53
}
47
54
48
55
this . _panelOpen = true ;
@@ -54,6 +61,7 @@ export class MdAutocompleteTrigger implements OnDestroy {
54
61
this . _overlayRef . detach ( ) ;
55
62
}
56
63
64
+ this . _optionWatcher . unsubscribe ( ) ;
57
65
this . _closeWatcher . unsubscribe ( ) ;
58
66
this . _panelOpen = false ;
59
67
}
@@ -71,10 +79,13 @@ export class MdAutocompleteTrigger implements OnDestroy {
71
79
* This method will close the panel if it receives a selection event from any of the options
72
80
* or a click on the backdrop.
73
81
*/
74
- private _watchForClose ( ) {
82
+ private _watchForClose ( ) : void {
75
83
// TODO(kara): add tab event watcher when adding keyboard events
84
+ if ( this . _closeWatcher ) {
85
+ this . _closeWatcher . unsubscribe ( ) ;
86
+ }
76
87
this . _closeWatcher = Observable . merge ( ...this . _getOptionObs ( ) , this . _overlayRef . backdropClick ( ) )
77
- . subscribe ( ( ) => this . closePanel ( ) ) ;
88
+ . subscribe ( ( event ) => this . _setValueAndClose ( event ) ) ;
78
89
}
79
90
80
91
/**
@@ -86,6 +97,23 @@ export class MdAutocompleteTrigger implements OnDestroy {
86
97
return this . autocomplete . options . map ( ( option ) => option . onSelect ) ;
87
98
}
88
99
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
+
89
117
private _createOverlay ( ) : void {
90
118
this . _portal = new TemplatePortal ( this . autocomplete . template , this . _vcr ) ;
91
119
this . _overlayRef = this . _overlay . create ( this . _getOverlayConfig ( ) ) ;
0 commit comments