Skip to content

Commit dfe5cac

Browse files
committed
refactor(material/chips): switch to lazy ripple rendering
1 parent cbac7f6 commit dfe5cac

File tree

9 files changed

+50
-33
lines changed

9 files changed

+50
-33
lines changed

src/material/chips/chip-option.html

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
<span matRipple class="mat-mdc-chip-ripple"
2-
[matRippleDisabled]="_isRippleDisabled()"
3-
[matRippleCentered]="_isRippleCentered"
4-
[matRippleTrigger]="_elementRef.nativeElement"></span>
51
<span class="mat-mdc-chip-focus-overlay"></span>
62

73
<span class="mdc-evolution-chip__cell mdc-evolution-chip__cell--primary">

src/material/chips/chip-row.html

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
<ng-container *ngIf="!_isEditing">
2-
<span matRipple class="mat-mdc-chip-ripple"
3-
[matRippleDisabled]="_isRippleDisabled()"
4-
[matRippleCentered]="_isRippleCentered"
5-
[matRippleTrigger]="_elementRef.nativeElement"></span>
6-
<span class="mat-mdc-chip-focus-overlay"></span>
7-
</ng-container>
8-
9-
101
<span class="mdc-evolution-chip__cell mdc-evolution-chip__cell--primary" role="gridcell"
112
matChipAction
123
[tabIndex]="tabIndex"

src/material/chips/chip-row.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ export class MatChipRow extends MatChip implements AfterViewInit {
203203
}
204204
}
205205

206+
override _isRippleDisabled(): boolean {
207+
return super._isRippleDisabled() || this._isEditing;
208+
}
209+
206210
/**
207211
* Gets the projected chip edit input, or the default input if none is projected in. One of these
208212
* two values is guaranteed to be defined.

src/material/chips/chip.html

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
<span matRipple class="mat-mdc-chip-ripple"
2-
[matRippleDisabled]="_isRippleDisabled()"
3-
[matRippleCentered]="_isRippleCentered"
4-
[matRippleTrigger]="_elementRef.nativeElement"></span>
51
<span class="mat-mdc-chip-focus-overlay"></span>
62

73
<span class="mdc-evolution-chip__cell mdc-evolution-chip__cell--primary">

src/material/chips/chip.spec.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ describe('MDC-based MatChip', () => {
1212
let chipNativeElement: HTMLElement;
1313
let chipInstance: MatChip;
1414
let chipRippleDebugElement: DebugElement;
15-
let chipRippleInstance: MatRipple;
1615

1716
let dir = 'ltr';
1817

@@ -74,9 +73,8 @@ describe('MDC-based MatChip', () => {
7473
fixture = TestBed.createComponent(BasicChip);
7574
fixture.detectChanges();
7675
chipDebugElement = fixture.debugElement.query(By.directive(MatChip))!;
77-
chipRippleDebugElement = chipDebugElement.query(By.directive(MatRipple))!;
78-
chipRippleInstance = chipRippleDebugElement.injector.get<MatRipple>(MatRipple);
79-
expect(chipRippleInstance.disabled)
76+
chipInstance = chipDebugElement.injector.get<MatChip>(MatChip);
77+
expect(chipInstance.ripple.disabled)
8078
.withContext('Expected basic chip ripples to be disabled.')
8179
.toBe(true);
8280
});
@@ -94,7 +92,6 @@ describe('MDC-based MatChip', () => {
9492
chipNativeElement = chipDebugElement.nativeElement;
9593
chipInstance = chipDebugElement.injector.get<MatChip>(MatChip);
9694
chipRippleDebugElement = chipDebugElement.query(By.directive(MatRipple))!;
97-
chipRippleInstance = chipRippleDebugElement.injector.get<MatRipple>(MatRipple);
9895
testComponent = fixture.debugElement.componentInstance;
9996
primaryAction = chipNativeElement.querySelector('.mdc-evolution-chip__action--primary')!;
10097
});
@@ -137,27 +134,27 @@ describe('MDC-based MatChip', () => {
137134
});
138135

139136
it('should be able to disable ripples with the `[rippleDisabled]` input', () => {
140-
expect(chipRippleInstance.disabled)
137+
expect(chipInstance.ripple.disabled)
141138
.withContext('Expected chip ripples to be enabled.')
142139
.toBe(false);
143140

144141
testComponent.rippleDisabled = true;
145142
fixture.detectChanges();
146143

147-
expect(chipRippleInstance.disabled)
144+
expect(chipInstance.ripple.disabled)
148145
.withContext('Expected chip ripples to be disabled.')
149146
.toBe(true);
150147
});
151148

152149
it('should disable ripples when the chip is disabled', () => {
153-
expect(chipRippleInstance.disabled)
150+
expect(chipInstance.ripple.disabled)
154151
.withContext('Expected chip ripples to be enabled.')
155152
.toBe(false);
156153

157154
testComponent.disabled = true;
158155
fixture.detectChanges();
159156

160-
expect(chipRippleInstance.disabled)
157+
expect(chipInstance.ripple.disabled)
161158
.withContext('Expected chip ripples to be disabled.')
162159
.toBe(true);
163160
});

src/material/chips/chip.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import {
2929
ContentChildren,
3030
QueryList,
3131
OnInit,
32+
DoCheck,
33+
inject,
3234
} from '@angular/core';
3335
import {DOCUMENT} from '@angular/common';
3436
import {
@@ -43,6 +45,7 @@ import {
4345
mixinTabIndex,
4446
mixinDisabled,
4547
RippleGlobalOptions,
48+
MatRippleLoader,
4649
} from '@angular/material/core';
4750
import {FocusMonitor} from '@angular/cdk/a11y';
4851
import {merge, Subject, Subscription} from 'rxjs';
@@ -123,14 +126,12 @@ export class MatChip
123126
CanColor,
124127
CanDisableRipple,
125128
CanDisable,
129+
DoCheck,
126130
HasTabIndex,
127131
OnDestroy
128132
{
129133
protected _document: Document;
130134

131-
/** Whether the ripple is centered on the chip. */
132-
readonly _isRippleCentered = false;
133-
134135
/** Emits when the chip is focused. */
135136
readonly _onFocus = new Subject<MatChipEvent>();
136137

@@ -251,11 +252,22 @@ export class MatChip
251252
* @deprecated Considered an implementation detail. To be removed.
252253
* @breaking-change 17.0.0
253254
*/
254-
@ViewChild(MatRipple) ripple: MatRipple;
255+
get ripple(): MatRipple {
256+
return this._rippleLoader?.getRipple(this._elementRef.nativeElement)!;
257+
}
258+
set ripple(v: MatRipple) {
259+
this._rippleLoader?.attachRipple(this._elementRef.nativeElement, v);
260+
}
255261

256262
/** Action receiving the primary set of user interactions. */
257263
@ViewChild(MatChipAction) primaryAction: MatChipAction;
258264

265+
/**
266+
* Handles the lazy creation of the MatButton ripple.
267+
* Used to improve initial load time of large applications.
268+
*/
269+
_rippleLoader: MatRippleLoader = inject(MatRippleLoader);
270+
259271
constructor(
260272
public _changeDetectorRef: ChangeDetectorRef,
261273
elementRef: ElementRef<HTMLElement>,
@@ -275,6 +287,11 @@ export class MatChip
275287
this.tabIndex = parseInt(tabIndex) ?? this.defaultTabIndex;
276288
}
277289
this._monitorFocus();
290+
291+
this._rippleLoader?.configureRipple(this._elementRef.nativeElement, {
292+
className: 'mat-mdc-chip-ripple',
293+
disabled: this._isRippleDisabled(),
294+
});
278295
}
279296

280297
ngOnInit() {
@@ -305,6 +322,10 @@ export class MatChip
305322
).subscribe(() => this._changeDetectorRef.markForCheck());
306323
}
307324

325+
ngDoCheck(): void {
326+
this._rippleLoader.setDisabled(this._elementRef.nativeElement, this._isRippleDisabled());
327+
}
328+
308329
ngOnDestroy() {
309330
this._focusMonitor.stopMonitoring(this._elementRef);
310331
this._actionChanges?.unsubscribe();

src/material/core/private/ripple-loader.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export class MatRippleLoader implements OnDestroy {
7575
config: {
7676
className?: string;
7777
centered?: boolean;
78+
disabled?: boolean;
7879
},
7980
): void {
8081
// Indicates that the ripple has not yet been rendered for this component.
@@ -89,6 +90,10 @@ export class MatRippleLoader implements OnDestroy {
8990
if (config.centered) {
9091
host.setAttribute(matRippleCentered, '');
9192
}
93+
94+
if (config.disabled) {
95+
host.setAttribute(matRippleDisabled, '');
96+
}
9297
}
9398

9499
/** Returns the ripple instance for the given host element. */

tools/public_api_guard/material/chips.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { InjectionToken } from '@angular/core';
3131
import { MatFormField } from '@angular/material/form-field';
3232
import { MatFormFieldControl } from '@angular/material/form-field';
3333
import { MatRipple } from '@angular/material/core';
34+
import { MatRippleLoader } from '@angular/material/core';
3435
import { NgControl } from '@angular/forms';
3536
import { NgForm } from '@angular/forms';
3637
import { NgZone } from '@angular/core';
@@ -61,7 +62,7 @@ export const MAT_CHIP_TRAILING_ICON: InjectionToken<unknown>;
6162
export const MAT_CHIPS_DEFAULT_OPTIONS: InjectionToken<MatChipsDefaultOptions>;
6263

6364
// @public
64-
export class MatChip extends _MatChipMixinBase implements OnInit, AfterViewInit, AfterContentInit, CanColor, CanDisableRipple, CanDisable, HasTabIndex, OnDestroy {
65+
export class MatChip extends _MatChipMixinBase implements OnInit, AfterViewInit, AfterContentInit, CanColor, CanDisableRipple, CanDisable, DoCheck, HasTabIndex, OnDestroy {
6566
constructor(_changeDetectorRef: ChangeDetectorRef, elementRef: ElementRef<HTMLElement>, _ngZone: NgZone, _focusMonitor: FocusMonitor, _document: any, animationMode?: string, _globalRippleOptions?: RippleGlobalOptions | undefined, tabIndex?: string);
6667
protected _allLeadingIcons: QueryList<MatChipAvatar>;
6768
protected _allRemoveIcons: QueryList<MatChipRemove>;
@@ -90,14 +91,15 @@ export class MatChip extends _MatChipMixinBase implements OnInit, AfterViewInit,
9091
protected _highlighted: boolean;
9192
id: string;
9293
_isBasicChip: boolean;
93-
readonly _isRippleCentered = false;
9494
_isRippleDisabled(): boolean;
9595
leadingIcon: MatChipAvatar;
9696
// (undocumented)
9797
ngAfterContentInit(): void;
9898
// (undocumented)
9999
ngAfterViewInit(): void;
100100
// (undocumented)
101+
ngDoCheck(): void;
102+
// (undocumented)
101103
ngOnDestroy(): void;
102104
// (undocumented)
103105
ngOnInit(): void;
@@ -114,7 +116,9 @@ export class MatChip extends _MatChipMixinBase implements OnInit, AfterViewInit,
114116
readonly removed: EventEmitter<MatChipEvent>;
115117
removeIcon: MatChipRemove;
116118
// @deprecated
117-
ripple: MatRipple;
119+
get ripple(): MatRipple;
120+
set ripple(v: MatRipple);
121+
_rippleLoader: MatRippleLoader;
118122
role: string | null;
119123
trailingIcon: MatChipTrailingIcon;
120124
get value(): any;
@@ -407,6 +411,8 @@ export class MatChipRow extends MatChip implements AfterViewInit {
407411
// (undocumented)
408412
_isEditing: boolean;
409413
// (undocumented)
414+
_isRippleDisabled(): boolean;
415+
// (undocumented)
410416
static ɵcmp: i0.ɵɵComponentDeclaration<MatChipRow, "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", never, { "color": { "alias": "color"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "disableRipple": { "alias": "disableRipple"; "required": false; }; "tabIndex": { "alias": "tabIndex"; "required": false; }; "editable": { "alias": "editable"; "required": false; }; }, { "edited": "edited"; }, ["contentEditInput"], ["mat-chip-avatar, [matChipAvatar]", "*", "[matChipEditInput]", "mat-chip-trailing-icon,[matChipRemove],[matChipTrailingIcon]"], false, never>;
411417
// (undocumented)
412418
static ɵfac: i0.ɵɵFactoryDeclaration<MatChipRow, [null, null, null, null, null, { optional: true; }, { optional: true; }, { attribute: "tabindex"; }]>;

tools/public_api_guard/material/core.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ export class MatRippleLoader implements OnDestroy {
403403
configureRipple(host: HTMLElement, config: {
404404
className?: string;
405405
centered?: boolean;
406+
disabled?: boolean;
406407
}): void;
407408
createRipple(host: HTMLElement): MatRipple | undefined;
408409
getRipple(host: HTMLElement): MatRipple | undefined;

0 commit comments

Comments
 (0)