Skip to content

Commit 5e67c1a

Browse files
committed
fix(material/chips): styling not updating when actions are removed (#26696)
Some of the chip styling depends on the presence of chips actions and it wasn't being updated when they were toggled. Fixes #26691. (cherry picked from commit 6c1da5e)
1 parent 4338e5e commit 5e67c1a

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

src/material/chips/chip.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';
1010
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
1111
import {
1212
AfterViewInit,
13+
AfterContentInit,
1314
Component,
1415
ChangeDetectionStrategy,
1516
ChangeDetectorRef,
@@ -25,6 +26,8 @@ import {
2526
ViewEncapsulation,
2627
ViewChild,
2728
Attribute,
29+
ContentChildren,
30+
QueryList,
2831
} from '@angular/core';
2932
import {DOCUMENT} from '@angular/common';
3033
import {
@@ -41,7 +44,7 @@ import {
4144
RippleGlobalOptions,
4245
} from '@angular/material/core';
4346
import {FocusMonitor} from '@angular/cdk/a11y';
44-
import {Subject} from 'rxjs';
47+
import {merge, Subject, Subscription} from 'rxjs';
4548
import {take} from 'rxjs/operators';
4649
import {MatChipAvatar, MatChipTrailingIcon, MatChipRemove} from './chip-icons';
4750
import {MatChipAction} from './chip-action';
@@ -112,7 +115,14 @@ const _MatChipMixinBase = mixinTabIndex(
112115
})
113116
export class MatChip
114117
extends _MatChipMixinBase
115-
implements AfterViewInit, CanColor, CanDisableRipple, CanDisable, HasTabIndex, OnDestroy
118+
implements
119+
AfterViewInit,
120+
AfterContentInit,
121+
CanColor,
122+
CanDisableRipple,
123+
CanDisable,
124+
HasTabIndex,
125+
OnDestroy
116126
{
117127
protected _document: Document;
118128

@@ -137,9 +147,24 @@ export class MatChip
137147
/** Whether moving focus into the chip is pending. */
138148
private _pendingFocus: boolean;
139149

150+
/** Subscription to changes in the chip's actions. */
151+
private _actionChanges: Subscription | undefined;
152+
140153
/** Whether animations for the chip are enabled. */
141154
_animationsDisabled: boolean;
142155

156+
/** All avatars present in the chip. */
157+
@ContentChildren(MAT_CHIP_AVATAR, {descendants: true})
158+
protected _allLeadingIcons: QueryList<MatChipAvatar>;
159+
160+
/** All trailing icons present in the chip. */
161+
@ContentChildren(MAT_CHIP_TRAILING_ICON, {descendants: true})
162+
protected _allTrailingIcons: QueryList<MatChipTrailingIcon>;
163+
164+
/** All remove icons present in the chip. */
165+
@ContentChildren(MAT_CHIP_REMOVE, {descendants: true})
166+
protected _allRemoveIcons: QueryList<MatChipRemove>;
167+
143168
_hasFocus() {
144169
return this._hasFocusInternal;
145170
}
@@ -259,8 +284,19 @@ export class MatChip
259284
}
260285
}
261286

287+
ngAfterContentInit(): void {
288+
// Since the styling depends on the presence of some
289+
// actions, we have to mark for check on changes.
290+
this._actionChanges = merge(
291+
this._allLeadingIcons.changes,
292+
this._allTrailingIcons.changes,
293+
this._allRemoveIcons.changes,
294+
).subscribe(() => this._changeDetectorRef.markForCheck());
295+
}
296+
262297
ngOnDestroy() {
263298
this._focusMonitor.stopMonitoring(this._elementRef);
299+
this._actionChanges?.unsubscribe();
264300
this.destroyed.emit({chip: this});
265301
this.destroyed.complete();
266302
}

tools/public_api_guard/material/chips.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,11 @@ export const MAT_CHIP_TRAILING_ICON: InjectionToken<unknown>;
6161
export const MAT_CHIPS_DEFAULT_OPTIONS: InjectionToken<MatChipsDefaultOptions>;
6262

6363
// @public
64-
export class MatChip extends _MatChipMixinBase implements AfterViewInit, CanColor, CanDisableRipple, CanDisable, HasTabIndex, OnDestroy {
64+
export class MatChip extends _MatChipMixinBase implements AfterViewInit, AfterContentInit, CanColor, CanDisableRipple, CanDisable, HasTabIndex, OnDestroy {
6565
constructor(_changeDetectorRef: ChangeDetectorRef, elementRef: ElementRef<HTMLElement>, _ngZone: NgZone, _focusMonitor: FocusMonitor, _document: any, animationMode?: string, _globalRippleOptions?: RippleGlobalOptions | undefined, tabIndex?: string);
66+
protected _allLeadingIcons: QueryList<MatChipAvatar>;
67+
protected _allRemoveIcons: QueryList<MatChipRemove>;
68+
protected _allTrailingIcons: QueryList<MatChipTrailingIcon>;
6669
_animationsDisabled: boolean;
6770
ariaDescription: string | null;
6871
_ariaDescriptionId: string;
@@ -91,6 +94,8 @@ export class MatChip extends _MatChipMixinBase implements AfterViewInit, CanColo
9194
_isRippleDisabled(): boolean;
9295
leadingIcon: MatChipAvatar;
9396
// (undocumented)
97+
ngAfterContentInit(): void;
98+
// (undocumented)
9499
ngAfterViewInit(): void;
95100
// (undocumented)
96101
ngOnDestroy(): void;
@@ -114,7 +119,7 @@ export class MatChip extends _MatChipMixinBase implements AfterViewInit, CanColo
114119
// (undocumented)
115120
protected _value: any;
116121
// (undocumented)
117-
static ɵcmp: i0.ɵɵComponentDeclaration<MatChip, "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", ["matChip"], { "color": "color"; "disabled": "disabled"; "disableRipple": "disableRipple"; "tabIndex": "tabIndex"; "role": "role"; "id": "id"; "ariaLabel": "aria-label"; "ariaDescription": "aria-description"; "value": "value"; "removable": "removable"; "highlighted": "highlighted"; }, { "removed": "removed"; "destroyed": "destroyed"; }, ["leadingIcon", "trailingIcon", "removeIcon"], ["mat-chip-avatar, [matChipAvatar]", "*", "mat-chip-trailing-icon,[matChipRemove],[matChipTrailingIcon]"], false, never>;
122+
static ɵcmp: i0.ɵɵComponentDeclaration<MatChip, "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", ["matChip"], { "color": "color"; "disabled": "disabled"; "disableRipple": "disableRipple"; "tabIndex": "tabIndex"; "role": "role"; "id": "id"; "ariaLabel": "aria-label"; "ariaDescription": "aria-description"; "value": "value"; "removable": "removable"; "highlighted": "highlighted"; }, { "removed": "removed"; "destroyed": "destroyed"; }, ["leadingIcon", "trailingIcon", "removeIcon", "_allLeadingIcons", "_allTrailingIcons", "_allRemoveIcons"], ["mat-chip-avatar, [matChipAvatar]", "*", "mat-chip-trailing-icon,[matChipRemove],[matChipTrailingIcon]"], false, never>;
118123
// (undocumented)
119124
static ɵfac: i0.ɵɵFactoryDeclaration<MatChip, [null, null, null, null, null, { optional: true; }, { optional: true; }, { attribute: "tabindex"; }]>;
120125
}

0 commit comments

Comments
 (0)