Skip to content

Commit aad7ff7

Browse files
crisbetojelbourn
authored andcommitted
fix(chips): preselected chip not highlighted on init inside OnPush component (#16868)
Fixes preselected chips not getting the `mat-chip-selected` class on init if they're inside an OnPush component. Fixes #16841.
1 parent cad0102 commit aad7ff7

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

src/material/chips/chip-list.spec.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
Type,
3030
ViewChild,
3131
ViewChildren,
32+
ChangeDetectionStrategy,
3233
} from '@angular/core';
3334
import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
3435
import {FormControl, FormsModule, NgForm, ReactiveFormsModule, Validators} from '@angular/forms';
@@ -1270,6 +1271,16 @@ describe('MatChipList', () => {
12701271
});
12711272
});
12721273

1274+
it('should preselected chip as selected inside an OnPush component', fakeAsync(() => {
1275+
fixture = createComponent(PreselectedChipInsideOnPush);
1276+
fixture.detectChanges();
1277+
tick();
1278+
fixture.detectChanges();
1279+
1280+
expect(fixture.nativeElement.querySelector('.mat-chip').classList)
1281+
.toContain('mat-chip-selected', 'Expected first chip to be selected.');
1282+
}));
1283+
12731284
function createComponent<T>(component: Type<T>, providers: Provider[] = [], animationsModule:
12741285
Type<NoopAnimationsModule> | Type<BrowserAnimationsModule> = NoopAnimationsModule):
12751286
ComponentFixture<T> {
@@ -1607,3 +1618,19 @@ class ChipListWithRemove {
16071618
this.chips.splice(event.chip.value, 1);
16081619
}
16091620
}
1621+
1622+
1623+
@Component({
1624+
template: `
1625+
<mat-form-field>
1626+
<mat-chip-list [formControl]="control">
1627+
<mat-chip>Pizza</mat-chip>
1628+
<mat-chip>Pasta</mat-chip>
1629+
</mat-chip-list>
1630+
</mat-form-field>
1631+
`,
1632+
changeDetection: ChangeDetectionStrategy.OnPush
1633+
})
1634+
class PreselectedChipInsideOnPush {
1635+
control = new FormControl('Pizza');
1636+
}

src/material/chips/chip.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
OnDestroy,
2323
Optional,
2424
Output,
25+
ChangeDetectorRef,
2526
} from '@angular/core';
2627
import {
2728
CanColor,
@@ -235,7 +236,9 @@ export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDes
235236
@Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS)
236237
globalRippleOptions: RippleGlobalOptions | null,
237238
// @breaking-change 8.0.0 `animationMode` parameter to become required.
238-
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string) {
239+
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,
240+
// @breaking-change 9.0.0 `_changeDetectorRef` parameter to become required.
241+
private _changeDetectorRef?: ChangeDetectorRef) {
239242
super(_elementRef);
240243

241244
this._addHostClassName();
@@ -269,6 +272,7 @@ export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDes
269272
if (!this._selected) {
270273
this._selected = true;
271274
this._dispatchSelectionChange();
275+
this._markForCheck();
272276
}
273277
}
274278

@@ -277,6 +281,7 @@ export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDes
277281
if (this._selected) {
278282
this._selected = false;
279283
this._dispatchSelectionChange();
284+
this._markForCheck();
280285
}
281286
}
282287

@@ -285,13 +290,15 @@ export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDes
285290
if (!this._selected) {
286291
this._selected = true;
287292
this._dispatchSelectionChange(true);
293+
this._markForCheck();
288294
}
289295
}
290296

291297
/** Toggles the current selected state of this chip. */
292298
toggleSelected(isUserInput: boolean = false): boolean {
293299
this._selected = !this.selected;
294300
this._dispatchSelectionChange(isUserInput);
301+
this._markForCheck();
295302
return this.selected;
296303
}
297304

@@ -374,6 +381,13 @@ export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDes
374381
selected: this._selected
375382
});
376383
}
384+
385+
private _markForCheck() {
386+
// @breaking-change 9.0.0 Remove this method once the _changeDetectorRef is a required param.
387+
if (this._changeDetectorRef) {
388+
this._changeDetectorRef.markForCheck();
389+
}
390+
}
377391
}
378392

379393

tools/public_api_guard/material/chips.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export declare class MatChip extends _MatChipMixinBase implements FocusableOptio
2525
readonly selectionChange: EventEmitter<MatChipSelectionChange>;
2626
trailingIcon: MatChipTrailingIcon;
2727
value: any;
28-
constructor(_elementRef: ElementRef<HTMLElement>, _ngZone: NgZone, platform: Platform, globalRippleOptions: RippleGlobalOptions | null, animationMode?: string);
28+
constructor(_elementRef: ElementRef<HTMLElement>, _ngZone: NgZone, platform: Platform, globalRippleOptions: RippleGlobalOptions | null, animationMode?: string, _changeDetectorRef?: ChangeDetectorRef | undefined);
2929
_addHostClassName(): void;
3030
_blur(): void;
3131
_handleClick(event: Event): void;

0 commit comments

Comments
 (0)