88
99import { BooleanInput , coerceBooleanProperty } from '@angular/cdk/coercion' ;
1010import { SelectionModel } from '@angular/cdk/collections' ;
11- import { Platform } from '@angular/cdk/platform' ;
1211import {
1312 ChangeDetectionStrategy ,
1413 ChangeDetectorRef ,
1514 Component ,
1615 ContentChildren ,
1716 ElementRef ,
1817 EventEmitter ,
19- Inject ,
2018 InjectionToken ,
2119 Input ,
22- NgZone ,
2320 OnDestroy ,
2421 OnInit ,
25- Optional ,
2622 Output ,
2723 QueryList ,
2824 ViewChild ,
2925 ViewEncapsulation ,
26+ inject ,
3027} from '@angular/core' ;
31- import {
32- MAT_RIPPLE_GLOBAL_OPTIONS ,
33- RippleGlobalOptions ,
34- ThemePalette ,
35- } from '@angular/material-experimental/mdc-core' ;
36- import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations' ;
28+ import { ThemePalette } from '@angular/material-experimental/mdc-core' ;
3729import { MatListBase , MatListItemBase } from './list-base' ;
3830import { LIST_OPTION , ListOption , MatListOptionCheckboxPosition } from './list-option-types' ;
3931import { MatListItemLine , MatListItemTitle } from './list-item-sections' ;
@@ -56,8 +48,9 @@ export interface SelectionList extends MatListBase {
5648 selectedOptions : SelectionModel < MatListOption > ;
5749 compareWith : ( o1 : any , o2 : any ) => boolean ;
5850 _value : string [ ] | null ;
59- _reportValueChange : ( ) => void ;
60- _onTouched : ( ) => void ;
51+ _reportValueChange ( ) : void ;
52+ _emitChangeEvent ( options : MatListOption [ ] ) : void ;
53+ _onTouched ( ) : void ;
6154}
6255
6356@Component ( {
@@ -83,7 +76,9 @@ export interface SelectionList extends MatListBase {
8376 '[class.mat-accent]' : 'color !== "primary" && color !== "warn"' ,
8477 '[class.mat-warn]' : 'color === "warn"' ,
8578 '[class._mat-animation-noopable]' : '_noopAnimations' ,
79+ '[attr.aria-selected]' : 'selected' ,
8680 '(blur)' : '_handleBlur()' ,
81+ '(click)' : '_toggleOnInteraction()' ,
8782 } ,
8883 templateUrl : 'list-option.html' ,
8984 encapsulation : ViewEncapsulation . None ,
@@ -97,7 +92,9 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
9792 @ContentChildren ( MatListItemLine , { descendants : true } ) _lines : QueryList < MatListItemLine > ;
9893 @ContentChildren ( MatListItemTitle , { descendants : true } ) _titles : QueryList < MatListItemTitle > ;
9994 @ViewChild ( 'unscopedContent' ) _unscopedContent : ElementRef < HTMLSpanElement > ;
100- @ViewChild ( 'text' ) _itemText : ElementRef < HTMLElement > ;
95+
96+ private _selectionList = inject ( SELECTION_LIST ) ;
97+ private _changeDetectorRef = inject ( ChangeDetectorRef ) ;
10198
10299 /**
103100 * Emits when the selected state of the option has changed.
@@ -158,24 +155,6 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
158155 */
159156 private _inputsInitialized = false ;
160157
161- constructor (
162- element : ElementRef ,
163- ngZone : NgZone ,
164- platform : Platform ,
165- @Inject ( SELECTION_LIST ) public _selectionList : SelectionList ,
166- private _changeDetectorRef : ChangeDetectorRef ,
167- @Optional ( ) @Inject ( MAT_RIPPLE_GLOBAL_OPTIONS ) globalRippleOptions ?: RippleGlobalOptions ,
168- @Optional ( ) @Inject ( ANIMATION_MODULE_TYPE ) animationMode ?: string ,
169- ) {
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' ) ;
177- }
178-
179158 ngOnInit ( ) {
180159 const list = this . _selectionList ;
181160
@@ -221,6 +200,15 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
221200 this . _hostElement . focus ( ) ;
222201 }
223202
203+ /** Gets the text label of the list option. Used for the typeahead functionality in the list. */
204+ getLabel ( ) {
205+ const titleElement = this . _titles ?. get ( 0 ) ?. _elementRef . nativeElement ;
206+ // If there is no explicit title element, the unscoped text content
207+ // is treated as the list item title.
208+ const labelEl = titleElement || this . _unscopedContent ?. nativeElement ;
209+ return labelEl ?. textContent || '' ;
210+ }
211+
224212 /** Whether a checkbox is shown at the given position. */
225213 _hasCheckboxAt ( position : MatListOptionCheckboxPosition ) : boolean {
226214 return this . _selectionList . multiple && this . _getCheckboxPosition ( ) === position ;
@@ -280,4 +268,22 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
280268 _markForCheck ( ) {
281269 this . _changeDetectorRef . markForCheck ( ) ;
282270 }
271+
272+ /** Toggles the option's value based on a user interacion. */
273+ _toggleOnInteraction ( ) {
274+ if ( ! this . disabled ) {
275+ if ( this . _selectionList . multiple ) {
276+ this . selected = ! this . selected ;
277+ this . _selectionList . _emitChangeEvent ( [ this ] ) ;
278+ } else if ( ! this . selected ) {
279+ this . selected = true ;
280+ this . _selectionList . _emitChangeEvent ( [ this ] ) ;
281+ }
282+ }
283+ }
284+
285+ /** Sets the tabindex of the list option. */
286+ _setTabindex ( value : number ) {
287+ this . _hostElement . setAttribute ( 'tabindex' , value + '' ) ;
288+ }
283289}
0 commit comments