@@ -26,6 +26,7 @@ import { MdcFloatingLabel } from '@angular-mdc/web/floating-label';
26
26
import { MdcMenu } from '@angular-mdc/web/menu' ;
27
27
import { MdcLineRipple } from '@angular-mdc/web/line-ripple' ;
28
28
import { MdcFormField , MdcFormFieldControl } from '@angular-mdc/web/form-field' ;
29
+ import { MdcList , MdcListItem } from '@angular-mdc/web/list' ;
29
30
30
31
import { MdcSelectIcon } from './select-icon' ;
31
32
import { MdcSelectHelperText } from './helper-text' ;
@@ -58,6 +59,7 @@ let nextUniqueId = 0;
58
59
'[class.mdc-select--disabled]' : 'disabled' ,
59
60
'[class.mdc-select--outlined]' : 'outlined' ,
60
61
'[class.mdc-select--required]' : 'required' ,
62
+ '[class.mdc-select--invalid]' : 'valid' ,
61
63
'[class.mdc-select--with-leading-icon]' : 'leadingIcon' ,
62
64
} ,
63
65
template : `
@@ -78,9 +80,9 @@ let nextUniqueId = 0;
78
80
(focus)="onFocus()">
79
81
<ng-content></ng-content>
80
82
</select>
81
- <label mdcFloatingLabel [for]="id">{{_floatingLabelValue()}}</label>
83
+ <label mdcFloatingLabel *ngIf="!outlined" [for]="id">{{_floatingLabelValue()}}</label>
82
84
<mdc-line-ripple *ngIf="!outlined"></mdc-line-ripple>
83
- <mdc-notched-outline *ngIf="outlined"></mdc-notched-outline>
85
+ <mdc-notched-outline *ngIf="outlined" [label]="_floatingLabelValue()" [for]="id" ></mdc-notched-outline>
84
86
` ,
85
87
providers : [
86
88
MdcRipple ,
@@ -118,15 +120,15 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
118
120
private _disabled : boolean = false ;
119
121
120
122
@Input ( )
121
- get floatingLabel ( ) : boolean { return this . _floatingLabel ; }
122
- set floatingLabel ( value : boolean ) {
123
- this . _floatingLabel = toBoolean ( value ) ;
123
+ get floatLabel ( ) : boolean { return this . _floatLabel ; }
124
+ set floatLabel ( value : boolean ) {
125
+ this . _floatLabel = toBoolean ( value ) ;
124
126
if ( this . outlined && this . getValue ( ) ) {
125
- this . _foundation . notchOutline ( this . _floatingLabel ) ;
127
+ this . _foundation . notchOutline ( this . _floatLabel ) ;
126
128
}
127
129
this . _changeDetectorRef . markForCheck ( ) ;
128
130
}
129
- private _floatingLabel : boolean = true ;
131
+ private _floatLabel : boolean = true ;
130
132
131
133
@Input ( )
132
134
get outlined ( ) : boolean { return this . _outlined ; }
@@ -199,14 +201,16 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
199
201
@Output ( ) readonly valueChange :
200
202
EventEmitter < { index : number , value : any } > = new EventEmitter < any > ( ) ;
201
203
202
- @ViewChild ( MdcFloatingLabel ) _selectLabel ! : MdcFloatingLabel ;
204
+ @ViewChild ( MdcFloatingLabel ) _floatingLabel ! : MdcFloatingLabel ;
203
205
@ViewChild ( MdcLineRipple ) _lineRipple ! : MdcLineRipple ;
204
206
@ViewChild ( MdcNotchedOutline ) _notchedOutline ! : MdcNotchedOutline ;
205
207
@ViewChild ( 'nativeInput' ) _nativeInput ! : ElementRef < HTMLInputElement > ;
206
208
@ViewChild ( 'nativeSelect' ) _nativeSelect ! : ElementRef < HTMLSelectElement > ;
207
209
@ViewChild ( 'selectedText' ) _selectedText ! : ElementRef < HTMLElement > ;
208
210
@ContentChild ( MdcMenu ) _selectMenu ! : MdcMenu ;
209
211
@ContentChild ( MdcSelectIcon ) leadingIcon ! : MdcSelectIcon ;
212
+ @ContentChild ( MdcList ) _list ! : MdcList ;
213
+ @ContentChildren ( MdcListItem , { descendants : true } ) _listItems ! : QueryList < MdcListItem > ;
210
214
211
215
/** View -> model callback called when value changes */
212
216
_onChange : ( value : any ) => void = ( ) => { } ;
@@ -216,7 +220,7 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
216
220
217
221
private _createAdapter ( ) {
218
222
return Object . assign (
219
- this . _getNativeSelectAdapterMethods ( ) ,
223
+ this . _list ? this . _getEnhancedSelectAdapterMethods ( ) : this . _getNativeSelectAdapterMethods ( ) ,
220
224
this . _getCommonAdapterMethods ( ) ,
221
225
this . _getOutlineAdapterMethods ( ) ,
222
226
this . _getLabelAdapterMethods ( )
@@ -259,6 +263,60 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
259
263
} ;
260
264
}
261
265
266
+ private _getEnhancedSelectAdapterMethods ( ) {
267
+ return {
268
+ // getValue: () => {
269
+ // const listItem = this.menuElement_.querySelector(strings.SELECTED_ITEM_SELECTOR);
270
+ // if (listItem && listItem.hasAttribute(strings.ENHANCED_VALUE_ATTR)) {
271
+ // return listItem.getAttribute(strings.ENHANCED_VALUE_ATTR);
272
+ // }
273
+ // return '';
274
+ // },
275
+ // setValue: (value: any) => {
276
+ // const element =
277
+ // /** @type {HTMLElement } */ (this.menuElement_.querySelector(`[${strings.ENHANCED_VALUE_ATTR}="${value}"]`));
278
+ // this.setEnhancedSelectedIndex_(element ? this.menu_.items.indexOf(element) : -1);
279
+ // },
280
+ // openMenu: () => {
281
+ // if (this.menu_ && !this.menu_.open) {
282
+ // this.menu_.open = true;
283
+ // this.menuOpened_ = true;
284
+ // this.selectedText_.setAttribute('aria-expanded', 'true');
285
+ // }
286
+ // },
287
+ // closeMenu: () => {
288
+ // if (this.menu_ && this.menu_.open) {
289
+ // this.menu_.open = false;
290
+ // }
291
+ // },
292
+ // isMenuOpen: () => this.menu_ && this.menuOpened_,
293
+ // setSelectedIndex: (index) => {
294
+ // this.setEnhancedSelectedIndex_(index);
295
+ // },
296
+ // setDisabled: (isDisabled: boolean) => {
297
+ // this.selectedText_.setAttribute('tabindex', isDisabled ? '-1' : '0');
298
+ // this.selectedText_.setAttribute('aria-disabled', isDisabled.toString());
299
+ // if (this.hiddenInput_) {
300
+ // this.hiddenInput_.disabled = isDisabled;
301
+ // }
302
+ // },
303
+ // checkValidity: () => {
304
+ // const classList = this.root_.classList;
305
+ // if (classList.contains(cssClasses.REQUIRED) && !classList.contains(cssClasses.DISABLED)) {
306
+ // // See notes for required attribute under https://www.w3.org/TR/html52/sec-forms.html#the-select-element
307
+ // // TL;DR: Invalid if no index is selected, or if the first index is selected and has an empty value.
308
+ // return this.selectedIndex !== -1 && (this.selectedIndex !== 0 || this.value);
309
+ // } else {
310
+ // return true;
311
+ // }
312
+ // },
313
+ // setValid: (isValid: boolean) => {
314
+ // this._selectedText.nativeElement.setAttribute('aria-invalid', (!isValid).toString());
315
+ // this._valid = isValid;
316
+ // }
317
+ } ;
318
+ }
319
+
262
320
private _getOutlineAdapterMethods ( ) {
263
321
return {
264
322
hasOutline : ( ) => ! ! this . _notchedOutline ,
@@ -269,8 +327,8 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
269
327
270
328
private _getLabelAdapterMethods ( ) {
271
329
return {
272
- floatLabel : ( shouldFloat : boolean ) => this . _selectLabel . float ( shouldFloat ) ,
273
- getLabelWidth : ( ) => this . _selectLabel ? this . _selectLabel . getWidth ( ) : 0
330
+ floatLabel : ( shouldFloat : boolean ) => this . _getFloatingLabel ( ) . float ( shouldFloat ) ,
331
+ getLabelWidth : ( ) => this . _hasFloatingLabel ( ) ? this . _getFloatingLabel ( ) . getWidth ( ) : 0
274
332
} ;
275
333
}
276
334
@@ -416,7 +474,7 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
416
474
}
417
475
418
476
_floatingLabelValue ( ) : string {
419
- return ! this . _floatingLabel && this . getValue ( ) ? '' : this . placeholder ;
477
+ return ! this . _hasFloatingLabel ( ) && this . getValue ( ) ? '' : this . placeholder ;
420
478
}
421
479
422
480
private _initializeSelection ( ) : void {
@@ -458,6 +516,14 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
458
516
}
459
517
}
460
518
519
+ private _hasFloatingLabel ( ) : boolean {
520
+ return this . placeholder && ( this . _floatingLabel || this . _notchedOutline ) ? true : false ;
521
+ }
522
+
523
+ private _getFloatingLabel ( ) : MdcFloatingLabel {
524
+ return this . _floatingLabel || this . _notchedOutline . floatingLabel ;
525
+ }
526
+
461
527
/**
462
528
* Calculates where the line ripple should start based on the x coordinate within the component.
463
529
*/
@@ -473,8 +539,8 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
473
539
private _setWidth ( ) : void {
474
540
if ( ! this . autosize ) { return ; }
475
541
476
- if ( this . _selectLabel && this . _selectLabel . elementRef . nativeElement . textContent ) {
477
- const labelLength = this . _selectLabel . elementRef . nativeElement . textContent . length ;
542
+ if ( this . _getFloatingLabel ( ) && this . _getFloatingLabel ( ) . elementRef . nativeElement . textContent ) {
543
+ const labelLength = this . _getFloatingLabel ( ) . elementRef . nativeElement . textContent ! . length ;
478
544
this . _getHostElement ( ) . style . setProperty ( 'width' , `${ labelLength } rem` ) ;
479
545
}
480
546
}
0 commit comments