Skip to content

Commit

Permalink
fixup! feat(material/button): make button ripples lazy
Browse files Browse the repository at this point in the history
  • Loading branch information
wagnermaciel committed Mar 31, 2023
1 parent c5b60fc commit 6a8e00f
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 159 deletions.
19 changes: 11 additions & 8 deletions src/material/button/button-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ import {
mixinDisabled,
mixinDisableRipple,
} from '@angular/material/core';
import {MatButtonRipple} from './button-ripple';
import {MAT_BUTTON_RIPPLE_UNINITIALIZED} from './button-lazy-loader';
import {MAT_BUTTON_RIPPLE_UNINITIALIZED, MatButtonLazyLoader} from './button-lazy-loader';

/** Inputs common to all buttons. */
export const MAT_BUTTON_INPUTS = ['disabled', 'disableRipple', 'color'];
Expand Down Expand Up @@ -100,6 +99,8 @@ export class MatButtonBase
{
private readonly _focusMonitor = inject(FocusMonitor);

_rippleLoader: MatButtonLazyLoader = inject(MatButtonLazyLoader);

/** Whether this button is a FAB. Used to apply the correct class on the ripple. */
_isFab = false;

Expand All @@ -109,17 +110,17 @@ export class MatButtonBase
* @breaking-change 16.0.0
*/
get ripple(): MatRipple {
if (this._ripple instanceof MatButtonRipple && !this._ripple._isAttached) {
this._ripple._renderRipple();
if (!this._ripple) {
this._ripple = this._rippleLoader._createMatRipple(this._elementRef.nativeElement);
}
return this._ripple;
return this._ripple!;
}
set ripple(v: MatRipple) {
this._ripple = v;
}

/** @docs-private Reference to the MatButtonRipple instance of the button. */
protected _ripple: MatRipple;
/** @docs-private Reference to the MatRipple instance of the button. */
protected _ripple?: MatRipple;

constructor(
elementRef: ElementRef,
Expand Down Expand Up @@ -165,7 +166,9 @@ export class MatButtonBase
}

_isRippleDisabled() {
this._ripple.disabled = this.disableRipple || this.disabled;
if (this._ripple) {
this._ripple.disabled = this.disableRipple || this.disabled;
}
}
}

Expand Down
31 changes: 30 additions & 1 deletion src/material/button/button-lazy-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,17 @@
*/

import {DOCUMENT} from '@angular/common';
import {ANIMATION_MODULE_TYPE, Injectable, NgZone, OnDestroy, inject} from '@angular/core';
import {
ANIMATION_MODULE_TYPE,
ElementRef,
Injectable,
NgZone,
OnDestroy,
inject,
} from '@angular/core';
import {
MAT_RIPPLE_GLOBAL_OPTIONS,
MatRipple,
RippleConfig,
RippleGlobalOptions,
RippleRenderer,
Expand Down Expand Up @@ -89,6 +97,27 @@ export class MatButtonLazyLoader implements OnDestroy {
rippleRenderer.setupTriggerEvents(button);
button.append(ripple);
}

_createMatRipple(button: HTMLElement): MatRipple | undefined {
if (!this._document) {
return;
}
button.querySelector('.mat-mdc-button-ripple')?.remove();
button.removeAttribute(MAT_BUTTON_RIPPLE_UNINITIALIZED);
const rippleEl = this._document!.createElement('span');
rippleEl.classList.add('mat-mdc-button-ripple');
const ripple = new MatRipple(
new ElementRef(rippleEl),
this._ngZone,
this._platform,
this._globalRippleOptions ? this._globalRippleOptions : undefined,
this._animationMode ? this._animationMode : undefined,
);
ripple._isInitialized = true;
ripple.trigger = button;
button.append(rippleEl);
return ripple;
}
}

/**
Expand Down
98 changes: 0 additions & 98 deletions src/material/button/button-ripple.ts

This file was deleted.

7 changes: 3 additions & 4 deletions src/material/button/button.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import {waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing';
import {ApplicationRef, Component, DebugElement} from '@angular/core';
import {By} from '@angular/platform-browser';
import {MatButtonModule, MatButton, MatFabDefaultOptions, MAT_FAB_DEFAULT_OPTIONS} from './index';
import {ThemePalette} from '@angular/material/core';
import {MatRipple, ThemePalette} from '@angular/material/core';
import {createMouseEvent, dispatchEvent} from '@angular/cdk/testing/private';
import {MatButtonRipple} from './button-ripple';

describe('MDC-based MatButton', () => {
beforeEach(waitForAsync(() => {
Expand Down Expand Up @@ -268,9 +267,9 @@ describe('MDC-based MatButton', () => {
let fixture: ComponentFixture<TestApp>;
let testComponent: TestApp;
let buttonDebugElement: DebugElement;
let buttonRippleInstance: MatButtonRipple;
let buttonRippleInstance: MatRipple;
let anchorDebugElement: DebugElement;
let anchorRippleInstance: MatButtonRipple;
let anchorRippleInstance: MatRipple;

beforeEach(() => {
fixture = TestBed.createComponent(TestApp);
Expand Down
6 changes: 0 additions & 6 deletions src/material/button/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
NgZone,
Optional,
ViewEncapsulation,
inject,
} from '@angular/core';
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';

Expand All @@ -27,7 +26,6 @@ import {
MatAnchorBase,
MatButtonBase,
} from './button-base';
import {MatButtonRipple} from './button-ripple';

/**
* Material Design button component. Users interact with a button to perform an action.
Expand All @@ -50,10 +48,8 @@ import {MatButtonRipple} from './button-ripple';
exportAs: 'matButton',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
hostDirectives: [MatButtonRipple],
})
export class MatButton extends MatButtonBase {
override _ripple = inject(MatButtonRipple);
constructor(
elementRef: ElementRef,
platform: Platform,
Expand Down Expand Up @@ -83,10 +79,8 @@ export class MatButton extends MatButtonBase {
styleUrls: ['button.css', 'button-high-contrast.css'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
hostDirectives: [MatButtonRipple],
})
export class MatAnchor extends MatAnchorBase {
override _ripple = inject(MatButtonRipple);
constructor(
elementRef: ElementRef,
platform: Platform,
Expand Down
10 changes: 0 additions & 10 deletions src/material/button/fab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
NgZone,
Optional,
ViewEncapsulation,
inject,
} from '@angular/core';
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';

Expand All @@ -30,7 +29,6 @@ import {
} from './button-base';
import {ThemePalette} from '@angular/material/core';
import {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';
import {MatButtonRipple} from './button-ripple';

/** Default FAB options that can be overridden. */
export interface MatFabDefaultOptions {
Expand Down Expand Up @@ -79,11 +77,9 @@ let buttonInputs = [...MAT_ANCHOR_INPUTS, 'extended'];
exportAs: 'matButton',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
hostDirectives: [MatButtonRipple],
})
export class MatFabButton extends MatButtonBase {
override _isFab = true;
override _ripple = inject(MatButtonRipple);

get extended(): boolean {
return this._extended;
Expand Down Expand Up @@ -120,11 +116,9 @@ export class MatFabButton extends MatButtonBase {
exportAs: 'matButton',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
hostDirectives: [MatButtonRipple],
})
export class MatMiniFabButton extends MatButtonBase {
override _isFab = true;
override _ripple = inject(MatButtonRipple);

constructor(
elementRef: ElementRef,
Expand Down Expand Up @@ -159,11 +153,9 @@ export class MatMiniFabButton extends MatButtonBase {
exportAs: 'matButton, matAnchor',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
hostDirectives: [MatButtonRipple],
})
export class MatFabAnchor extends MatAnchor {
override _isFab = true;
override _ripple = inject(MatButtonRipple);

get extended(): boolean {
return this._extended;
Expand Down Expand Up @@ -200,11 +192,9 @@ export class MatFabAnchor extends MatAnchor {
exportAs: 'matButton, matAnchor',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
hostDirectives: [MatButtonRipple],
})
export class MatMiniFabAnchor extends MatAnchor {
override _isFab = true;
override _ripple = inject(MatButtonRipple);

constructor(
elementRef: ElementRef,
Expand Down
21 changes: 14 additions & 7 deletions src/material/button/icon-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
NgZone,
Optional,
ViewEncapsulation,
inject,
} from '@angular/core';
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';

Expand All @@ -27,7 +26,7 @@ import {
MatAnchorBase,
MatButtonBase,
} from './button-base';
import {MatButtonRipple} from './button-ripple';
import {MatRipple} from '@angular/material/core';

/**
* Material Design icon button component. This type of button displays a single interactive icon for
Expand All @@ -43,18 +42,28 @@ import {MatButtonRipple} from './button-ripple';
exportAs: 'matButton',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
hostDirectives: [MatButtonRipple],
})
export class MatIconButton extends MatButtonBase {
override _ripple = inject(MatButtonRipple);
/**
* Reference to the MatRipple instance of the button.
* @deprecated Considered an implementation detail. To be removed.
* @breaking-change 16.0.0
*/
override get ripple(): MatRipple {
if (!this._ripple) {
this._ripple = this._rippleLoader._createMatRipple(this._elementRef.nativeElement);
this._ripple!.centered = true;
}
return this._ripple!;
}

constructor(
elementRef: ElementRef,
platform: Platform,
ngZone: NgZone,
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,
) {
super(elementRef, platform, ngZone, animationMode);
this._ripple.centered = true;
}
}

Expand All @@ -72,10 +81,8 @@ export class MatIconButton extends MatButtonBase {
exportAs: 'matButton, matAnchor',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
hostDirectives: [MatButtonRipple],
})
export class MatIconAnchor extends MatAnchorBase {
override _ripple = inject(MatButtonRipple);
constructor(
elementRef: ElementRef,
platform: Platform,
Expand Down
Loading

0 comments on commit 6a8e00f

Please sign in to comment.