@@ -17,6 +17,9 @@ import {
17
17
Optional ,
18
18
QueryList ,
19
19
ViewEncapsulation ,
20
+ OnChanges ,
21
+ OnDestroy ,
22
+ ChangeDetectorRef ,
20
23
} from '@angular/core' ;
21
24
import {
22
25
CanDisableRipple ,
@@ -25,6 +28,8 @@ import {
25
28
setLines ,
26
29
mixinDisableRipple ,
27
30
} from '@angular/material/core' ;
31
+ import { Subject } from 'rxjs' ;
32
+ import { takeUntil } from 'rxjs/operators' ;
28
33
29
34
// Boilerplate for applying mixins to MatList.
30
35
/** @docs -private */
@@ -52,7 +57,19 @@ export const _MatListItemMixinBase: CanDisableRippleCtor & typeof MatListItemBas
52
57
encapsulation : ViewEncapsulation . None ,
53
58
changeDetection : ChangeDetectionStrategy . OnPush ,
54
59
} )
55
- export class MatNavList extends _MatListMixinBase implements CanDisableRipple { }
60
+ export class MatNavList extends _MatListMixinBase implements CanDisableRipple , OnChanges ,
61
+ OnDestroy {
62
+ /** Emits when the state of the list changes. */
63
+ _stateChanges = new Subject < void > ( ) ;
64
+
65
+ ngOnChanges ( ) {
66
+ this . _stateChanges . next ( ) ;
67
+ }
68
+
69
+ ngOnDestroy ( ) {
70
+ this . _stateChanges . complete ( ) ;
71
+ }
72
+ }
56
73
57
74
@Component ( {
58
75
moduleId : module . id ,
@@ -67,7 +84,10 @@ export class MatNavList extends _MatListMixinBase implements CanDisableRipple {}
67
84
encapsulation : ViewEncapsulation . None ,
68
85
changeDetection : ChangeDetectionStrategy . OnPush ,
69
86
} )
70
- export class MatList extends _MatListMixinBase implements CanDisableRipple {
87
+ export class MatList extends _MatListMixinBase implements CanDisableRipple , OnChanges , OnDestroy {
88
+ /** Emits when the state of the list changes. */
89
+ _stateChanges = new Subject < void > ( ) ;
90
+
71
91
/**
72
92
* @deprecated _elementRef parameter to be made required.
73
93
* @breaking -change 8.0.0
@@ -94,6 +114,14 @@ export class MatList extends _MatListMixinBase implements CanDisableRipple {
94
114
95
115
return null ;
96
116
}
117
+
118
+ ngOnChanges ( ) {
119
+ this . _stateChanges . next ( ) ;
120
+ }
121
+
122
+ ngOnDestroy ( ) {
123
+ this . _stateChanges . complete ( ) ;
124
+ }
97
125
}
98
126
99
127
/**
@@ -143,17 +171,20 @@ export class MatListSubheaderCssMatStyler {}
143
171
changeDetection : ChangeDetectionStrategy . OnPush ,
144
172
} )
145
173
export class MatListItem extends _MatListItemMixinBase implements AfterContentInit ,
146
- CanDisableRipple {
174
+ CanDisableRipple , OnDestroy {
147
175
private _isInteractiveList : boolean = false ;
148
176
private _list ?: MatNavList | MatList ;
177
+ private _destroyed = new Subject < void > ( ) ;
149
178
150
179
@ContentChildren ( MatLine ) _lines : QueryList < MatLine > ;
151
180
@ContentChild ( MatListAvatarCssMatStyler ) _avatar : MatListAvatarCssMatStyler ;
152
181
@ContentChild ( MatListIconCssMatStyler ) _icon : MatListIconCssMatStyler ;
153
182
154
183
constructor ( private _element : ElementRef < HTMLElement > ,
155
184
@Optional ( ) navList ?: MatNavList ,
156
- @Optional ( ) list ?: MatList ) {
185
+ @Optional ( ) list ?: MatList ,
186
+ // @breaking -change 8.0.0 `_changeDetectorRef` to be made into a required parameter.
187
+ _changeDetectorRef ?: ChangeDetectorRef ) {
157
188
super ( ) ;
158
189
this . _isInteractiveList = ! ! ( navList || ( list && list . _getListType ( ) === 'action-list' ) ) ;
159
190
this . _list = navList || list ;
@@ -165,12 +196,26 @@ export class MatListItem extends _MatListItemMixinBase implements AfterContentIn
165
196
if ( element . nodeName . toLowerCase ( ) === 'button' && ! element . hasAttribute ( 'type' ) ) {
166
197
element . setAttribute ( 'type' , 'button' ) ;
167
198
}
199
+
200
+ // @breaking -change 8.0.0 Remove null check for _changeDetectorRef.
201
+ if ( this . _list && _changeDetectorRef ) {
202
+ // React to changes in the state of the parent list since
203
+ // some of the item's properties depend on it (e.g. `disableRipple`).
204
+ this . _list . _stateChanges . pipe ( takeUntil ( this . _destroyed ) ) . subscribe ( ( ) => {
205
+ _changeDetectorRef . markForCheck ( ) ;
206
+ } ) ;
207
+ }
168
208
}
169
209
170
210
ngAfterContentInit ( ) {
171
211
setLines ( this . _lines , this . _element ) ;
172
212
}
173
213
214
+ ngOnDestroy ( ) {
215
+ this . _destroyed . next ( ) ;
216
+ this . _destroyed . complete ( ) ;
217
+ }
218
+
174
219
/** Whether this list item should show a ripple effect when clicked. */
175
220
_isRippleDisabled ( ) {
176
221
return ! this . _isInteractiveList || this . disableRipple ||
0 commit comments