@@ -49,7 +49,8 @@ import {
49
49
ThemePalette ,
50
50
} from '@angular/material/core' ;
51
51
import { ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ;
52
- import { Subscription } from 'rxjs' ;
52
+ import { Subject } from 'rxjs' ;
53
+ import { takeUntil } from 'rxjs/operators' ;
53
54
import { MatListAvatarCssMatStyler , MatListIconCssMatStyler } from './list' ;
54
55
55
56
@@ -103,8 +104,8 @@ export class MatSelectionListChange {
103
104
// its theme. The accent theme palette is the default and doesn't need to be set.
104
105
'[class.mat-primary]' : 'color === "primary"' ,
105
106
'[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' ,
108
109
} ,
109
110
templateUrl : 'list-option.html' ,
110
111
encapsulation : ViewEncapsulation . None ,
@@ -359,17 +360,17 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
359
360
/** View to model callback that should be called whenever the selected options change. */
360
361
private _onChange : ( value : any ) => void = ( _ : any ) => { } ;
361
362
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 ;
364
365
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 > ( ) ;
367
368
368
369
/** View to model callback that should be called if the list or its options lost focus. */
369
370
_onTouched : ( ) => void = ( ) => { } ;
370
371
371
372
/** Whether the list has been destroyed. */
372
- private _destroyed : boolean ;
373
+ private _isDestroyed : boolean ;
373
374
374
375
constructor ( private _element : ElementRef < HTMLElement > , @Attribute ( 'tabindex' ) tabIndex : string ) {
375
376
super ( ) ;
@@ -385,13 +386,22 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
385
386
. skipPredicate ( ( ) => false )
386
387
. withAllowedModifierKeys ( [ 'shiftKey' ] ) ;
387
388
388
- if ( this . _tempValues ) {
389
- this . _setOptionsFromValues ( this . _tempValues ) ;
390
- this . _tempValues = null ;
389
+ if ( this . _value ) {
390
+ this . _setOptionsFromValues ( this . _value ) ;
391
391
}
392
392
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
+
393
403
// 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 => {
395
405
if ( event . added ) {
396
406
for ( let item of event . added ) {
397
407
item . selected = true ;
@@ -417,8 +427,9 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
417
427
}
418
428
419
429
ngOnDestroy ( ) {
420
- this . _destroyed = true ;
421
- this . _modelChanges . unsubscribe ( ) ;
430
+ this . _destroyed . next ( ) ;
431
+ this . _destroyed . complete ( ) ;
432
+ this . _isDestroyed = true ;
422
433
}
423
434
424
435
/** Focuses the selection list. */
@@ -504,8 +515,10 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
504
515
// Stop reporting value changes after the list has been destroyed. This avoids
505
516
// cases where the list might wrongly reset its value once it is removed, but
506
517
// 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 ;
509
522
}
510
523
}
511
524
@@ -516,10 +529,10 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
516
529
517
530
/** Implemented as part of ControlValueAccessor. */
518
531
writeValue ( values : string [ ] ) : void {
532
+ this . _value = values ;
533
+
519
534
if ( this . options ) {
520
535
this . _setOptionsFromValues ( values || [ ] ) ;
521
- } else {
522
- this . _tempValues = values ;
523
536
}
524
537
}
525
538
0 commit comments