@@ -26,6 +26,7 @@ import { MdcFloatingLabel } from '@angular-mdc/web/floating-label';
2626import { MdcMenu } from '@angular-mdc/web/menu' ;
2727import { MdcLineRipple } from '@angular-mdc/web/line-ripple' ;
2828import { MdcFormField , MdcFormFieldControl } from '@angular-mdc/web/form-field' ;
29+ import { MdcList , MdcListItem } from '@angular-mdc/web/list' ;
2930
3031import { MdcSelectIcon } from './select-icon' ;
3132import { MdcSelectHelperText } from './helper-text' ;
@@ -58,6 +59,7 @@ let nextUniqueId = 0;
5859 '[class.mdc-select--disabled]' : 'disabled' ,
5960 '[class.mdc-select--outlined]' : 'outlined' ,
6061 '[class.mdc-select--required]' : 'required' ,
62+ '[class.mdc-select--invalid]' : 'valid' ,
6163 '[class.mdc-select--with-leading-icon]' : 'leadingIcon' ,
6264 } ,
6365 template : `
@@ -78,9 +80,9 @@ let nextUniqueId = 0;
7880 (focus)="onFocus()">
7981 <ng-content></ng-content>
8082 </select>
81- <label mdcFloatingLabel [for]="id">{{_floatingLabelValue()}}</label>
83+ <label mdcFloatingLabel *ngIf="!outlined" [for]="id">{{_floatingLabelValue()}}</label>
8284 <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>
8486 ` ,
8587 providers : [
8688 MdcRipple ,
@@ -118,15 +120,15 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
118120 private _disabled : boolean = false ;
119121
120122 @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 ) ;
124126 if ( this . outlined && this . getValue ( ) ) {
125- this . _foundation . notchOutline ( this . _floatingLabel ) ;
127+ this . _foundation . notchOutline ( this . _floatLabel ) ;
126128 }
127129 this . _changeDetectorRef . markForCheck ( ) ;
128130 }
129- private _floatingLabel : boolean = true ;
131+ private _floatLabel : boolean = true ;
130132
131133 @Input ( )
132134 get outlined ( ) : boolean { return this . _outlined ; }
@@ -199,14 +201,16 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
199201 @Output ( ) readonly valueChange :
200202 EventEmitter < { index : number , value : any } > = new EventEmitter < any > ( ) ;
201203
202- @ViewChild ( MdcFloatingLabel ) _selectLabel ! : MdcFloatingLabel ;
204+ @ViewChild ( MdcFloatingLabel ) _floatingLabel ! : MdcFloatingLabel ;
203205 @ViewChild ( MdcLineRipple ) _lineRipple ! : MdcLineRipple ;
204206 @ViewChild ( MdcNotchedOutline ) _notchedOutline ! : MdcNotchedOutline ;
205207 @ViewChild ( 'nativeInput' ) _nativeInput ! : ElementRef < HTMLInputElement > ;
206208 @ViewChild ( 'nativeSelect' ) _nativeSelect ! : ElementRef < HTMLSelectElement > ;
207209 @ViewChild ( 'selectedText' ) _selectedText ! : ElementRef < HTMLElement > ;
208210 @ContentChild ( MdcMenu ) _selectMenu ! : MdcMenu ;
209211 @ContentChild ( MdcSelectIcon ) leadingIcon ! : MdcSelectIcon ;
212+ @ContentChild ( MdcList ) _list ! : MdcList ;
213+ @ContentChildren ( MdcListItem , { descendants : true } ) _listItems ! : QueryList < MdcListItem > ;
210214
211215 /** View -> model callback called when value changes */
212216 _onChange : ( value : any ) => void = ( ) => { } ;
@@ -216,7 +220,7 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
216220
217221 private _createAdapter ( ) {
218222 return Object . assign (
219- this . _getNativeSelectAdapterMethods ( ) ,
223+ this . _list ? this . _getEnhancedSelectAdapterMethods ( ) : this . _getNativeSelectAdapterMethods ( ) ,
220224 this . _getCommonAdapterMethods ( ) ,
221225 this . _getOutlineAdapterMethods ( ) ,
222226 this . _getLabelAdapterMethods ( )
@@ -259,6 +263,60 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
259263 } ;
260264 }
261265
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+
262320 private _getOutlineAdapterMethods ( ) {
263321 return {
264322 hasOutline : ( ) => ! ! this . _notchedOutline ,
@@ -269,8 +327,8 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
269327
270328 private _getLabelAdapterMethods ( ) {
271329 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
274332 } ;
275333 }
276334
@@ -416,7 +474,7 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
416474 }
417475
418476 _floatingLabelValue ( ) : string {
419- return ! this . _floatingLabel && this . getValue ( ) ? '' : this . placeholder ;
477+ return ! this . _hasFloatingLabel ( ) && this . getValue ( ) ? '' : this . placeholder ;
420478 }
421479
422480 private _initializeSelection ( ) : void {
@@ -458,6 +516,14 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
458516 }
459517 }
460518
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+
461527 /**
462528 * Calculates where the line ripple should start based on the x coordinate within the component.
463529 */
@@ -473,8 +539,8 @@ export class MdcSelect implements OnInit, ControlValueAccessor, OnDestroy {
473539 private _setWidth ( ) : void {
474540 if ( ! this . autosize ) { return ; }
475541
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 ;
478544 this . _getHostElement ( ) . style . setProperty ( 'width' , `${ labelLength } rem` ) ;
479545 }
480546 }
0 commit comments