@@ -41,6 +41,7 @@ export interface MdcSelectedData {
41
41
}
42
42
43
43
let nextUniqueId = 0 ;
44
+ let uniqueIdCounter = 0 ;
44
45
45
46
@Directive ( {
46
47
selector : 'mdc-select-label'
@@ -51,15 +52,6 @@ export class MdcSelectLabel {
51
52
constructor ( public elementRef : ElementRef ) { }
52
53
}
53
54
54
- @Directive ( {
55
- selector : 'mdc-selected-text'
56
- } )
57
- export class MdcSelectedText {
58
- @HostBinding ( 'class.mdc-select__selected-text' ) isHostClass = true ;
59
-
60
- constructor ( public elementRef : ElementRef ) { }
61
- }
62
-
63
55
@Directive ( {
64
56
selector : 'mdc-select-menu' ,
65
57
} )
@@ -81,30 +73,56 @@ export class MdcSelectItems {
81
73
}
82
74
83
75
@Directive ( {
84
- selector : 'mdc-select-item'
76
+ selector : 'mdc-select-item' ,
77
+ host : {
78
+ '[id]' : 'id' ,
79
+ 'role' : 'option' ,
80
+ '[attr.aria-selected]' : 'selected' ,
81
+ '[attr.aria-disabled]' : 'disabled' ,
82
+ }
85
83
} )
86
84
export class MdcSelectItem {
85
+ private _selected = false ;
87
86
private _disabled : boolean = false ;
87
+ private _id = `mdc-select-item-${ uniqueIdCounter ++ } ` ;
88
88
89
- @Input ( ) value : string ;
89
+ /** The unique ID of the option. */
90
+ get id ( ) : string { return this . _id ; }
91
+
92
+ /** Whether or not the option is currently selected. */
93
+ get selected ( ) : boolean { return this . _selected ; }
94
+
95
+ /** The displayed label of the option. */
96
+ get label ( ) : string {
97
+ return ( this . elementRef . nativeElement . textContent || '' ) . trim ( ) ;
98
+ }
99
+
100
+ @Input ( ) value : any ;
90
101
@Input ( )
91
102
get disabled ( ) : boolean {
92
103
return this . _disabled ;
93
104
}
94
105
set disabled ( value : boolean ) {
95
- this . _disabled = value ;
96
- if ( value ) {
97
- this . _renderer . setAttribute ( this . elementRef . nativeElement , 'aria-disabled' , 'true' ) ;
98
- this . tabIndex = - 1 ;
99
- } else {
100
- this . _renderer . removeAttribute ( this . elementRef . nativeElement , 'aria-disabled' ) ;
101
- this . tabIndex = 0 ;
102
- }
106
+ this . _disabled = toBoolean ( value ) ;
107
+ value ? this . tabIndex = - 1 : this . tabIndex = 0 ;
103
108
}
104
109
@HostBinding ( 'class.mdc-list-item' ) isHostClass = true ;
105
- @HostBinding ( 'attr.role' ) role : string = 'option' ;
106
110
@HostBinding ( 'tabindex' ) tabIndex : number = 0 ;
107
111
112
+ /** Selects the option. */
113
+ select ( ) : void {
114
+ this . _selected = true ;
115
+ }
116
+
117
+ /** Deselects the option. */
118
+ deselect ( ) : void {
119
+ this . _selected = false ;
120
+ }
121
+
122
+ focus ( ) : void {
123
+ this . elementRef . nativeElement . focus ( ) ;
124
+ }
125
+
108
126
constructor (
109
127
private _renderer : Renderer2 ,
110
128
public elementRef : ElementRef ) { }
@@ -117,8 +135,7 @@ export class MdcSelectItem {
117
135
} ,
118
136
template :
119
137
`
120
- <mdc-select-label *ngIf="!value">{{label}}</mdc-select-label>
121
- <mdc-selected-text>{{selectedText}}</mdc-selected-text>
138
+ <mdc-select-label>{{label}}</mdc-select-label>
122
139
<mdc-select-menu>
123
140
<mdc-select-items>
124
141
<ng-content></ng-content>
@@ -133,22 +150,28 @@ export class MdcSelectItem {
133
150
export class MdcSelect implements AfterViewInit , ControlValueAccessor , OnChanges , OnDestroy {
134
151
private _itemsSubscription : ISubscription ;
135
152
private _scrollStream : ISubscription ;
136
- private _open : boolean = false ;
137
153
private _label : string = '' ;
138
- private _value : string = '' ;
154
+ private _value : any ;
139
155
private _uniqueId : string = `mdc-select-${ ++ nextUniqueId } ` ;
140
156
private _menuFactory : any ;
141
- private _controlValueAccessorChangeFn : ( value : any ) => void = ( ) => { } ;
142
- onTouched : ( ) => any = ( ) => { } ;
143
- selectedText : string = '' ;
157
+ private _controlValueAccessorChangeFn : ( value : any ) => void = ( value ) => { } ;
158
+ private _onChange : ( value : any ) => void = ( ) => { } ;
159
+ private _onTouched = ( ) => { } ;
144
160
145
161
@Input ( ) id : string = this . _uniqueId ;
146
162
@Input ( ) name : string | null = null ;
147
- @Input ( ) label : string = '' ;
148
163
@Input ( )
149
- get value ( ) : string { return this . _foundation . getValue ( ) ; }
150
- set value ( v : string ) {
151
- this . _value = v ;
164
+ get label ( ) : string { return this . _label ; }
165
+ set label ( value : string ) {
166
+ this . _label = value ;
167
+ }
168
+ @Input ( )
169
+ get value ( ) : any { return this . _value ; }
170
+ set value ( newValue : any ) {
171
+ if ( newValue !== this . _value ) {
172
+ this . writeValue ( newValue ) ;
173
+ this . _value = newValue ;
174
+ }
152
175
}
153
176
@Input ( )
154
177
get disabled ( ) : boolean { return this . isDisabled ( ) ; }
@@ -215,7 +238,7 @@ export class MdcSelect implements AfterViewInit, ControlValueAccessor, OnChanges
215
238
} ,
216
239
isMenuOpen : ( ) => this . _menuFactory . open ,
217
240
setSelectedTextContent : ( textContent : string ) => {
218
- this . selectedText = textContent ;
241
+ this . _label = textContent ;
219
242
} ,
220
243
getNumberOfOptions : ( ) => {
221
244
return this . options ? this . options . length : 0 ;
@@ -247,6 +270,7 @@ export class MdcSelect implements AfterViewInit, ControlValueAccessor, OnChanges
247
270
value : this . _foundation . getValue ( ) ,
248
271
} ) ;
249
272
this . _controlValueAccessorChangeFn ( this . _foundation . getValue ( ) ) ;
273
+ this . setSelectedIndex ( this . _foundation . getSelectedIndex ( ) ) ;
250
274
} ,
251
275
getWindowInnerHeight : ( ) => isBrowser ( ) ? window . innerHeight : 0 ,
252
276
} ;
@@ -271,8 +295,8 @@ export class MdcSelect implements AfterViewInit, ControlValueAccessor, OnChanges
271
295
this . _itemsSubscription = this . options . changes . subscribe ( _ => {
272
296
this . _foundation . resize ( ) ;
273
297
} ) ;
274
- this . _foundation . init ( ) ;
275
298
this . _menuFactory = new MDCSimpleMenu ( this . selectMenu . elementRef . nativeElement ) ;
299
+ this . _foundation . init ( ) ;
276
300
}
277
301
278
302
ngOnDestroy ( ) {
@@ -288,10 +312,10 @@ export class MdcSelect implements AfterViewInit, ControlValueAccessor, OnChanges
288
312
}
289
313
290
314
ngOnChanges ( changes : { [ key : string ] : SimpleChange } ) {
291
- let closeOnScroll = changes [ 'closeOnScroll' ] ;
315
+ let _closeOnScroll = changes [ 'closeOnScroll' ] ;
292
316
293
- if ( closeOnScroll && isBrowser ( ) ) {
294
- if ( closeOnScroll . currentValue && ( ! this . _scrollStream || this . _scrollStream . closed ) ) {
317
+ if ( _closeOnScroll && isBrowser ( ) ) {
318
+ if ( _closeOnScroll . currentValue && ( ! this . _scrollStream || this . _scrollStream . closed ) ) {
295
319
this . _scrollStream = Observable . fromEvent ( window , 'scroll' )
296
320
. subscribe ( res => {
297
321
if ( this . _mdcAdapter . isMenuOpen ( ) ) {
@@ -306,28 +330,47 @@ export class MdcSelect implements AfterViewInit, ControlValueAccessor, OnChanges
306
330
}
307
331
}
308
332
309
- writeValue ( value : any ) {
310
- this . value = value ;
333
+ writeValue ( value : any ) : void {
334
+ if ( this . options ) {
335
+ this . setSelectionByValue ( value ) ;
336
+ }
311
337
}
312
338
313
- registerOnChange ( fn : ( value : any ) => void ) {
339
+ registerOnChange ( fn : ( value : any ) => void ) : void {
314
340
this . _controlValueAccessorChangeFn = fn ;
315
341
}
316
342
317
- registerOnTouched ( fn : any ) {
318
- this . onTouched = fn ;
343
+ registerOnTouched ( fn : ( ) => { } ) : void {
344
+ this . _onTouched = fn ;
319
345
}
320
346
321
347
getValue ( ) : string {
322
348
return this . _foundation . getValue ( ) ;
323
349
}
324
350
351
+ setLabel ( text : string ) : void {
352
+ this . _label = text ;
353
+ }
354
+
325
355
getSelectedIndex ( ) : number {
326
356
return this . _foundation . getSelectedIndex ( ) ;
327
357
}
328
358
329
- setSelectedIndex ( selectedIndex : number ) : void {
330
- this . _foundation . setSelectedIndex ( selectedIndex ) ;
359
+ clearSelection ( ) : void {
360
+ this . options . forEach ( ( _ ) => _ . deselect ) ;
361
+ }
362
+
363
+ setSelectionByValue ( value : any ) : void {
364
+ this . clearSelection ( ) ;
365
+ if ( value ) {
366
+ this . setSelectedIndex ( this . options . toArray ( ) . findIndex ( ( _ ) => _ . value == value ) ) ;
367
+ }
368
+ }
369
+
370
+ setSelectedIndex ( index : number ) : void {
371
+ this . clearSelection ( ) ;
372
+ this . _foundation . setSelectedIndex ( index ) ;
373
+ this . options . toArray ( ) [ this . _foundation . getSelectedIndex ( ) ] . select ( ) ;
331
374
}
332
375
333
376
open ( index : number = 0 ) : void {
0 commit comments