88
99import { BooleanInput , coerceBooleanProperty } from '@angular/cdk/coercion' ;
1010import { SelectionModel } from '@angular/cdk/collections' ;
11- import { Platform } from '@angular/cdk/platform' ;
1211import {
12+ ANIMATION_MODULE_TYPE ,
1313 ChangeDetectionStrategy ,
1414 ChangeDetectorRef ,
1515 Component ,
@@ -33,10 +33,10 @@ import {
3333 RippleGlobalOptions ,
3434 ThemePalette ,
3535} from '@angular/material-experimental/mdc-core' ;
36- import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations' ;
3736import { MatListBase , MatListItemBase } from './list-base' ;
3837import { LIST_OPTION , ListOption , MatListOptionCheckboxPosition } from './list-option-types' ;
3938import { MatListItemLine , MatListItemTitle } from './list-item-sections' ;
39+ import { Platform } from '@angular/cdk/platform' ;
4040
4141/**
4242 * Injection token that can be used to reference instances of an `SelectionList`. It serves
@@ -56,8 +56,9 @@ export interface SelectionList extends MatListBase {
5656 selectedOptions : SelectionModel < MatListOption > ;
5757 compareWith : ( o1 : any , o2 : any ) => boolean ;
5858 _value : string [ ] | null ;
59- _reportValueChange : ( ) => void ;
60- _onTouched : ( ) => void ;
59+ _reportValueChange ( ) : void ;
60+ _emitChangeEvent ( options : MatListOption [ ] ) : void ;
61+ _onTouched ( ) : void ;
6162}
6263
6364@Component ( {
@@ -83,7 +84,9 @@ export interface SelectionList extends MatListBase {
8384 '[class.mat-accent]' : 'color !== "primary" && color !== "warn"' ,
8485 '[class.mat-warn]' : 'color === "warn"' ,
8586 '[class._mat-animation-noopable]' : '_noopAnimations' ,
87+ '[attr.aria-selected]' : 'selected' ,
8688 '(blur)' : '_handleBlur()' ,
89+ '(click)' : '_toggleOnInteraction()' ,
8790 } ,
8891 templateUrl : 'list-option.html' ,
8992 encapsulation : ViewEncapsulation . None ,
@@ -97,7 +100,6 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
97100 @ContentChildren ( MatListItemLine , { descendants : true } ) _lines : QueryList < MatListItemLine > ;
98101 @ContentChildren ( MatListItemTitle , { descendants : true } ) _titles : QueryList < MatListItemTitle > ;
99102 @ViewChild ( 'unscopedContent' ) _unscopedContent : ElementRef < HTMLSpanElement > ;
100- @ViewChild ( 'text' ) _itemText : ElementRef < HTMLElement > ;
101103
102104 /**
103105 * Emits when the selected state of the option has changed.
@@ -159,21 +161,17 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
159161 private _inputsInitialized = false ;
160162
161163 constructor (
162- element : ElementRef ,
164+ elementRef : ElementRef < HTMLElement > ,
163165 ngZone : NgZone ,
166+ @Inject ( SELECTION_LIST ) private _selectionList : SelectionList ,
164167 platform : Platform ,
165- @Inject ( SELECTION_LIST ) public _selectionList : SelectionList ,
166168 private _changeDetectorRef : ChangeDetectorRef ,
167- @Optional ( ) @Inject ( MAT_RIPPLE_GLOBAL_OPTIONS ) globalRippleOptions ?: RippleGlobalOptions ,
169+ @Optional ( )
170+ @Inject ( MAT_RIPPLE_GLOBAL_OPTIONS )
171+ globalRippleOptions ?: RippleGlobalOptions ,
168172 @Optional ( ) @Inject ( ANIMATION_MODULE_TYPE ) animationMode ?: string ,
169173 ) {
170- super ( element , ngZone , _selectionList , platform , globalRippleOptions , animationMode ) ;
171-
172- // By default, we mark all options as unselected. The MDC list foundation will
173- // automatically update the attribute based on selection. Note that we need to
174- // initially set this because MDC does not set the default attributes for list
175- // items but expects items to be set up properly in the static markup.
176- element . nativeElement . setAttribute ( 'aria-selected' , 'false' ) ;
174+ super ( elementRef , ngZone , _selectionList , platform , globalRippleOptions , animationMode ) ;
177175 }
178176
179177 ngOnInit ( ) {
@@ -221,6 +219,15 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
221219 this . _hostElement . focus ( ) ;
222220 }
223221
222+ /** Gets the text label of the list option. Used for the typeahead functionality in the list. */
223+ getLabel ( ) {
224+ const titleElement = this . _titles ?. get ( 0 ) ?. _elementRef . nativeElement ;
225+ // If there is no explicit title element, the unscoped text content
226+ // is treated as the list item title.
227+ const labelEl = titleElement || this . _unscopedContent ?. nativeElement ;
228+ return labelEl ?. textContent || '' ;
229+ }
230+
224231 /** Whether a checkbox is shown at the given position. */
225232 _hasCheckboxAt ( position : MatListOptionCheckboxPosition ) : boolean {
226233 return this . _selectionList . multiple && this . _getCheckboxPosition ( ) === position ;
@@ -280,4 +287,22 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
280287 _markForCheck ( ) {
281288 this . _changeDetectorRef . markForCheck ( ) ;
282289 }
290+
291+ /** Toggles the option's value based on a user interacion. */
292+ _toggleOnInteraction ( ) {
293+ if ( ! this . disabled ) {
294+ if ( this . _selectionList . multiple ) {
295+ this . selected = ! this . selected ;
296+ this . _selectionList . _emitChangeEvent ( [ this ] ) ;
297+ } else if ( ! this . selected ) {
298+ this . selected = true ;
299+ this . _selectionList . _emitChangeEvent ( [ this ] ) ;
300+ }
301+ }
302+ }
303+
304+ /** Sets the tabindex of the list option. */
305+ _setTabindex ( value : number ) {
306+ this . _hostElement . setAttribute ( 'tabindex' , value + '' ) ;
307+ }
283308}
0 commit comments