@@ -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 ,
@@ -359,17 +360,17 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
359360 /** View to model callback that should be called whenever the selected options change. */
360361 private _onChange : ( value : any ) => void = ( _ : any ) => { } ;
361362
362- /** Used for storing the values that were assigned before the options were initialized . */
363- private _tempValues : string [ ] | null ;
363+ /** Keeps track of the currently-selected value . */
364+ private _value : string [ ] | null ;
364365
365- /** Subscription to sync value changes in the SelectionModel back to the SelectionList . */
366- private _modelChanges = Subscription . EMPTY ;
366+ /** Emits when the list has been destroyed . */
367+ private _destroyed = new Subject < void > ( ) ;
367368
368369 /** View to model callback that should be called if the list or its options lost focus. */
369370 _onTouched : ( ) => void = ( ) => { } ;
370371
371372 /** Whether the list has been destroyed. */
372- private _destroyed : boolean ;
373+ private _isDestroyed : boolean ;
373374
374375 constructor ( private _element : ElementRef < HTMLElement > , @Attribute ( 'tabindex' ) tabIndex : string ) {
375376 super ( ) ;
@@ -385,13 +386,22 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
385386 . skipPredicate ( ( ) => false )
386387 . withAllowedModifierKeys ( [ 'shiftKey' ] ) ;
387388
388- if ( this . _tempValues ) {
389- this . _setOptionsFromValues ( this . _tempValues ) ;
390- this . _tempValues = null ;
389+ if ( this . _value ) {
390+ this . _setOptionsFromValues ( this . _value ) ;
391391 }
392392
393+ this . options . changes . pipe ( takeUntil ( this . _destroyed ) ) . subscribe ( ( ) => {
394+ if ( this . _value ) {
395+ // Needs to be deferred, because we're changing bindings as the result of a query
396+ // change which results in a "Changed after checked error".
397+ Promise . resolve ( ) . then ( ( ) => {
398+ this . _setOptionsFromValues ( this . _value || [ ] ) ;
399+ } ) ;
400+ }
401+ } ) ;
402+
393403 // Sync external changes to the model back to the options.
394- this . _modelChanges = this . selectedOptions . onChange . subscribe ( event => {
404+ this . selectedOptions . onChange . pipe ( takeUntil ( this . _destroyed ) ) . subscribe ( event => {
395405 if ( event . added ) {
396406 for ( let item of event . added ) {
397407 item . selected = true ;
@@ -417,8 +427,9 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
417427 }
418428
419429 ngOnDestroy ( ) {
420- this . _destroyed = true ;
421- this . _modelChanges . unsubscribe ( ) ;
430+ this . _destroyed . next ( ) ;
431+ this . _destroyed . complete ( ) ;
432+ this . _isDestroyed = true ;
422433 }
423434
424435 /** Focuses the selection list. */
@@ -504,8 +515,10 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
504515 // Stop reporting value changes after the list has been destroyed. This avoids
505516 // cases where the list might wrongly reset its value once it is removed, but
506517 // the form control is still live.
507- if ( this . options && ! this . _destroyed ) {
508- this . _onChange ( this . _getSelectedOptionValues ( ) ) ;
518+ if ( this . options && ! this . _isDestroyed ) {
519+ const value = this . _getSelectedOptionValues ( ) ;
520+ this . _onChange ( value ) ;
521+ this . _value = value ;
509522 }
510523 }
511524
@@ -516,10 +529,10 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
516529
517530 /** Implemented as part of ControlValueAccessor. */
518531 writeValue ( values : string [ ] ) : void {
532+ this . _value = values ;
533+
519534 if ( this . options ) {
520535 this . _setOptionsFromValues ( values || [ ] ) ;
521- } else {
522- this . _tempValues = values ;
523536 }
524537 }
525538
0 commit comments