@@ -49,7 +49,8 @@ import {
4949 ThemePalette ,
5050} from '@angular/material/core' ;
5151import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ;
52- import { Subscription } from 'rxjs' ;
52+ import { Subject } from 'rxjs' ;
53+ import { takeUntil } from 'rxjs/operators' ;
5354import { MatListAvatarCssMatStyler , MatListIconCssMatStyler } from './list' ;
5455
5556
@@ -103,8 +104,8 @@ export class MatSelectionListChange {
103104 // its theme. The accent theme palette is the default and doesn't need to be set.
104105 '[class.mat-primary]' : 'color === "primary"' ,
105106 '[class.mat-warn]' : 'color === "warn"' ,
106- '[attr.aria-selected]' : 'selected.toString() ' ,
107- '[attr.aria-disabled]' : 'disabled.toString() ' ,
107+ '[attr.aria-selected]' : 'selected' ,
108+ '[attr.aria-disabled]' : 'disabled' ,
108109 } ,
109110 templateUrl : 'list-option.html' ,
110111 encapsulation : ViewEncapsulation . None ,
@@ -177,13 +178,19 @@ export class MatListOption extends _MatListOptionMixinBase
177178 }
178179
179180 ngOnInit ( ) {
181+ const list = this . selectionList ;
182+
183+ if ( list . _value && list . _value . some ( value => list . compareWith ( value , this . _value ) ) ) {
184+ this . _setSelected ( true ) ;
185+ }
186+
187+ const wasSelected = this . _selected ;
188+
180189 // List options that are selected at initialization can't be reported properly to the form
181190 // control. This is because it takes some time until the selection-list knows about all
182191 // available options. Also it can happen that the ControlValueAccessor has an initial value
183192 // that should be used instead. Deferring the value change report to the next tick ensures
184193 // that the form control value is not being overwritten.
185- const wasSelected = this . _selected ;
186-
187194 Promise . resolve ( ) . then ( ( ) => {
188195 if ( this . _selected || wasSelected ) {
189196 this . selected = true ;
@@ -337,7 +344,7 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
337344 * options should appear as selected. The first argument is the value of an options. The second
338345 * one is a value from the selected value. A boolean must be returned.
339346 */
340- @Input ( ) compareWith : ( o1 : any , o2 : any ) => boolean ;
347+ @Input ( ) compareWith : ( o1 : any , o2 : any ) => boolean = ( a1 , a2 ) => a1 === a2 ;
341348
342349 /** Whether the selection list is disabled. */
343350 @Input ( )
@@ -359,17 +366,17 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
359366 /** View to model callback that should be called whenever the selected options change. */
360367 private _onChange : ( value : any ) => void = ( _ : any ) => { } ;
361368
362- /** Used for storing the values that were assigned before the options were initialized . */
363- private _tempValues : string [ ] | null ;
369+ /** Keeps track of the currently-selected value . */
370+ _value : string [ ] | null ;
364371
365- /** Subscription to sync value changes in the SelectionModel back to the SelectionList . */
366- private _modelChanges = Subscription . EMPTY ;
372+ /** Emits when the list has been destroyed . */
373+ private _destroyed = new Subject < void > ( ) ;
367374
368375 /** View to model callback that should be called if the list or its options lost focus. */
369376 _onTouched : ( ) => void = ( ) => { } ;
370377
371378 /** Whether the list has been destroyed. */
372- private _destroyed : boolean ;
379+ private _isDestroyed : boolean ;
373380
374381 constructor ( private _element : ElementRef < HTMLElement > , @Attribute ( 'tabindex' ) tabIndex : string ) {
375382 super ( ) ;
@@ -385,13 +392,12 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
385392 . skipPredicate ( ( ) => false )
386393 . withAllowedModifierKeys ( [ 'shiftKey' ] ) ;
387394
388- if ( this . _tempValues ) {
389- this . _setOptionsFromValues ( this . _tempValues ) ;
390- this . _tempValues = null ;
395+ if ( this . _value ) {
396+ this . _setOptionsFromValues ( this . _value ) ;
391397 }
392398
393399 // Sync external changes to the model back to the options.
394- this . _modelChanges = this . selectedOptions . onChange . subscribe ( event => {
400+ this . selectedOptions . onChange . pipe ( takeUntil ( this . _destroyed ) ) . subscribe ( event => {
395401 if ( event . added ) {
396402 for ( let item of event . added ) {
397403 item . selected = true ;
@@ -417,8 +423,9 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
417423 }
418424
419425 ngOnDestroy ( ) {
420- this . _destroyed = true ;
421- this . _modelChanges . unsubscribe ( ) ;
426+ this . _destroyed . next ( ) ;
427+ this . _destroyed . complete ( ) ;
428+ this . _isDestroyed = true ;
422429 }
423430
424431 /** Focuses the selection list. */
@@ -504,8 +511,10 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
504511 // Stop reporting value changes after the list has been destroyed. This avoids
505512 // cases where the list might wrongly reset its value once it is removed, but
506513 // the form control is still live.
507- if ( this . options && ! this . _destroyed ) {
508- this . _onChange ( this . _getSelectedOptionValues ( ) ) ;
514+ if ( this . options && ! this . _isDestroyed ) {
515+ const value = this . _getSelectedOptionValues ( ) ;
516+ this . _onChange ( value ) ;
517+ this . _value = value ;
509518 }
510519 }
511520
@@ -516,10 +525,10 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
516525
517526 /** Implemented as part of ControlValueAccessor. */
518527 writeValue ( values : string [ ] ) : void {
528+ this . _value = values ;
529+
519530 if ( this . options ) {
520531 this . _setOptionsFromValues ( values || [ ] ) ;
521- } else {
522- this . _tempValues = values ;
523532 }
524533 }
525534
@@ -546,11 +555,7 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
546555 const correspondingOption = this . options . find ( option => {
547556 // Skip options that are already in the model. This allows us to handle cases
548557 // where the same primitive value is selected multiple times.
549- if ( option . selected ) {
550- return false ;
551- }
552-
553- return this . compareWith ? this . compareWith ( option . value , value ) : option . value === value ;
558+ return option . selected ? false : this . compareWith ( option . value , value ) ;
554559 } ) ;
555560
556561 if ( correspondingOption ) {
0 commit comments