Skip to content

Commit 0ab3dce

Browse files
crisbetoandrewseguin
authored andcommitted
fix(material-experimental/mdc-snack-bar): avoid hard reference to base components and align API (#21425)
The MDC snack bar was set up to extend the base `MatSnackBar` directly which has a reference to the base snack bar components. This means that the code and styles from the base components will be pulled in, even though it isn't being used. These changes move the snack bar logic into a base class that is extended by the default and MDC implementations. While working on these changes, I also noticed that the simple snack bar components was called `SimpleSnackBar` in the default implementation and `MatSimpleSnackBar` for MDC. I've aligned the naming in order to make it easier to migrate. (cherry picked from commit ffc1de4)
1 parent 6cec795 commit 0ab3dce

File tree

9 files changed

+87
-42
lines changed

9 files changed

+87
-42
lines changed

src/dev-app/mdc-snack-bar/mdc-snack-bar-demo.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88

99
import {Directionality} from '@angular/cdk/bidi';
1010
import {Component, TemplateRef, ViewChild, ViewEncapsulation} from '@angular/core';
11-
import {MatSnackBar} from '@angular/material-experimental/mdc-snack-bar';
1211
import {
12+
MatSnackBar,
1313
MatSnackBarConfig,
1414
MatSnackBarHorizontalPosition,
1515
MatSnackBarVerticalPosition,
16-
} from '@angular/material/snack-bar';
16+
} from '@angular/material-experimental/mdc-snack-bar';
1717

1818
@Component({
1919
selector: 'mdc-snack-bar-demo',

src/material-experimental/mdc-snack-bar/module.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {NgModule} from '@angular/core';
1313
import {MatButtonModule} from '@angular/material-experimental/mdc-button';
1414
import {MatCommonModule} from '@angular/material-experimental/mdc-core';
1515

16-
import {MatSimpleSnackBar} from './simple-snack-bar';
16+
import {SimpleSnackBar} from './simple-snack-bar';
1717
import {MatSnackBarContainer} from './snack-bar-container';
1818
import {MatSnackBarAction, MatSnackBarActions, MatSnackBarLabel} from './snack-bar-content';
1919

@@ -27,7 +27,7 @@ import {MatSnackBarAction, MatSnackBarActions, MatSnackBarLabel} from './snack-b
2727
MatSnackBarAction,
2828
],
2929
declarations: [
30-
MatSimpleSnackBar,
30+
SimpleSnackBar,
3131
MatSnackBarContainer,
3232
MatSnackBarLabel,
3333
MatSnackBarActions,

src/material-experimental/mdc-snack-bar/public-api.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ export {
1616
MatSnackBarConfig,
1717
MatSnackBarDismiss,
1818
MatSnackBarRef,
19-
SimpleSnackBar,
2019
MAT_SNACK_BAR_DATA,
2120
MAT_SNACK_BAR_DEFAULT_OPTIONS,
2221
MAT_SNACK_BAR_DEFAULT_OPTIONS_FACTORY,

src/material-experimental/mdc-snack-bar/simple-snack-bar.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,10 @@
77
*/
88

99
import {ChangeDetectionStrategy, Component, Inject, ViewEncapsulation} from '@angular/core';
10-
import {
11-
MAT_SNACK_BAR_DATA,
12-
TextOnlySnackBar,
13-
MatSnackBarRef,
14-
SimpleSnackBar,
15-
} from '@angular/material/snack-bar';
10+
import {MAT_SNACK_BAR_DATA, TextOnlySnackBar, MatSnackBarRef} from '@angular/material/snack-bar';
1611

1712
@Component({
18-
selector: 'mat-simple-snack-bar',
13+
selector: 'simple-snack-bar',
1914
templateUrl: 'simple-snack-bar.html',
2015
styleUrls: ['simple-snack-bar.css'],
2116
exportAs: 'matSnackBar',
@@ -25,7 +20,7 @@ import {
2520
'class': 'mat-mdc-simple-snack-bar',
2621
},
2722
})
28-
export class MatSimpleSnackBar implements TextOnlySnackBar {
23+
export class SimpleSnackBar implements TextOnlySnackBar {
2924
constructor(
3025
public snackBarRef: MatSnackBarRef<SimpleSnackBar>,
3126
@Inject(MAT_SNACK_BAR_DATA) public data: {message: string; action: string},

src/material-experimental/mdc-snack-bar/snack-bar.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {NoopAnimationsModule} from '@angular/platform-browser/animations';
1414
import {
1515
MAT_SNACK_BAR_DATA,
1616
MAT_SNACK_BAR_DEFAULT_OPTIONS,
17-
MatSimpleSnackBar,
17+
SimpleSnackBar,
1818
MatSnackBar,
1919
MatSnackBarConfig,
2020
MatSnackBarContainer,
@@ -239,7 +239,7 @@ describe('MatSnackBar', () => {
239239

240240
viewContainerFixture.detectChanges();
241241

242-
expect(snackBarRef.instance instanceof MatSimpleSnackBar)
242+
expect(snackBarRef.instance instanceof SimpleSnackBar)
243243
.withContext('Expected the snack bar content component to be SimpleSnackBar')
244244
.toBe(true);
245245
expect(snackBarRef.instance.snackBarRef)
@@ -266,7 +266,7 @@ describe('MatSnackBar', () => {
266266

267267
viewContainerFixture.detectChanges();
268268

269-
expect(snackBarRef.instance instanceof MatSimpleSnackBar)
269+
expect(snackBarRef.instance instanceof SimpleSnackBar)
270270
.withContext('Expected the snack bar content component to be SimpleSnackBar')
271271
.toBe(true);
272272
expect(snackBarRef.instance.snackBarRef)

src/material-experimental/mdc-snack-bar/snack-bar.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,36 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Injectable} from '@angular/core';
10-
import {MatSnackBar as BaseMatSnackBar} from '@angular/material/snack-bar';
9+
import {LiveAnnouncer} from '@angular/cdk/a11y';
10+
import {BreakpointObserver} from '@angular/cdk/layout';
11+
import {Overlay} from '@angular/cdk/overlay';
12+
import {Inject, Injectable, Injector, Optional, SkipSelf} from '@angular/core';
13+
import {
14+
MatSnackBarConfig,
15+
MAT_SNACK_BAR_DEFAULT_OPTIONS,
16+
_MatSnackBarBase,
17+
} from '@angular/material/snack-bar';
1118
import {MatSnackBarModule} from './module';
12-
import {MatSimpleSnackBar} from './simple-snack-bar';
19+
import {SimpleSnackBar} from './simple-snack-bar';
1320
import {MatSnackBarContainer} from './snack-bar-container';
1421

1522
/**
1623
* Service to dispatch Material Design snack bar messages.
1724
*/
1825
@Injectable({providedIn: MatSnackBarModule})
19-
export class MatSnackBar extends BaseMatSnackBar {
20-
protected override simpleSnackBarComponent = MatSimpleSnackBar;
26+
export class MatSnackBar extends _MatSnackBarBase {
27+
protected override simpleSnackBarComponent = SimpleSnackBar;
2128
protected override snackBarContainerComponent = MatSnackBarContainer;
2229
protected override handsetCssClass = 'mat-mdc-snack-bar-handset';
30+
31+
constructor(
32+
overlay: Overlay,
33+
live: LiveAnnouncer,
34+
injector: Injector,
35+
breakpointObserver: BreakpointObserver,
36+
@Optional() @SkipSelf() parentSnackBar: MatSnackBar,
37+
@Inject(MAT_SNACK_BAR_DEFAULT_OPTIONS) defaultConfig: MatSnackBarConfig,
38+
) {
39+
super(overlay, live, injector, breakpointObserver, parentSnackBar, defaultConfig);
40+
}
2341
}

src/material-experimental/mdc-snack-bar/testing/snack-bar-harness.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
1212
import {Component, TemplateRef, ViewChild} from '@angular/core';
1313

1414
describe('MDC-based MatSnackBarHarness', () => {
15-
runHarnessTests(MatSnackBarModule, MatSnackBar, MatSnackBarHarness as any);
15+
runHarnessTests(MatSnackBarModule, MatSnackBar as any, MatSnackBarHarness as any);
1616
});
1717

1818
describe('MDC-based MatSnackBarHarness (MDC only behavior)', () => {

src/material/snack-bar/snack-bar.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,8 @@ export function MAT_SNACK_BAR_DEFAULT_OPTIONS_FACTORY(): MatSnackBarConfig {
4444
return new MatSnackBarConfig();
4545
}
4646

47-
/**
48-
* Service to dispatch Material Design snack bar messages.
49-
*/
50-
@Injectable({providedIn: MatSnackBarModule})
51-
export class MatSnackBar implements OnDestroy {
47+
@Injectable()
48+
export abstract class _MatSnackBarBase implements OnDestroy {
5249
/**
5350
* Reference to the current snack bar in the view *at this level* (in the Angular injector tree).
5451
* If there is a parent snack-bar service, all operations should delegate to that parent
@@ -57,13 +54,13 @@ export class MatSnackBar implements OnDestroy {
5754
private _snackBarRefAtThisLevel: MatSnackBarRef<any> | null = null;
5855

5956
/** The component that should be rendered as the snack bar's simple component. */
60-
protected simpleSnackBarComponent: Type<TextOnlySnackBar> = SimpleSnackBar;
57+
protected abstract simpleSnackBarComponent: Type<TextOnlySnackBar>;
6158

6259
/** The container component that attaches the provided template or component. */
63-
protected snackBarContainerComponent: Type<_SnackBarContainer> = MatSnackBarContainer;
60+
protected abstract snackBarContainerComponent: Type<_SnackBarContainer>;
6461

6562
/** The CSS class to apply for handset mode. */
66-
protected handsetCssClass = 'mat-snack-bar-handset';
63+
protected abstract handsetCssClass: string;
6764

6865
/** Reference to the currently opened snackbar at *any* level. */
6966
get _openedSnackBarRef(): MatSnackBarRef<any> | null {
@@ -84,7 +81,7 @@ export class MatSnackBar implements OnDestroy {
8481
private _live: LiveAnnouncer,
8582
private _injector: Injector,
8683
private _breakpointObserver: BreakpointObserver,
87-
@Optional() @SkipSelf() private _parentSnackBar: MatSnackBar,
84+
@Optional() @SkipSelf() private _parentSnackBar: _MatSnackBarBase,
8885
@Inject(MAT_SNACK_BAR_DEFAULT_OPTIONS) private _defaultConfig: MatSnackBarConfig,
8986
) {}
9087

@@ -311,3 +308,24 @@ export class MatSnackBar implements OnDestroy {
311308
});
312309
}
313310
}
311+
312+
/**
313+
* Service to dispatch Material Design snack bar messages.
314+
*/
315+
@Injectable({providedIn: MatSnackBarModule})
316+
export class MatSnackBar extends _MatSnackBarBase {
317+
protected simpleSnackBarComponent = SimpleSnackBar;
318+
protected snackBarContainerComponent = MatSnackBarContainer;
319+
protected handsetCssClass = 'mat-snack-bar-handset';
320+
321+
constructor(
322+
overlay: Overlay,
323+
live: LiveAnnouncer,
324+
injector: Injector,
325+
breakpointObserver: BreakpointObserver,
326+
@Optional() @SkipSelf() parentSnackBar: MatSnackBar,
327+
@Inject(MAT_SNACK_BAR_DEFAULT_OPTIONS) defaultConfig: MatSnackBarConfig,
328+
) {
329+
super(overlay, live, injector, breakpointObserver, parentSnackBar, defaultConfig);
330+
}
331+
}

tools/public_api_guard/material/snack-bar.md

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,14 @@ export const MAT_SNACK_BAR_DEFAULT_OPTIONS: InjectionToken<MatSnackBarConfig<any
4949
export function MAT_SNACK_BAR_DEFAULT_OPTIONS_FACTORY(): MatSnackBarConfig;
5050

5151
// @public
52-
export class MatSnackBar implements OnDestroy {
53-
constructor(_overlay: Overlay, _live: LiveAnnouncer, _injector: Injector, _breakpointObserver: BreakpointObserver, _parentSnackBar: MatSnackBar, _defaultConfig: MatSnackBarConfig);
54-
dismiss(): void;
52+
export class MatSnackBar extends _MatSnackBarBase {
53+
constructor(overlay: Overlay, live: LiveAnnouncer, injector: Injector, breakpointObserver: BreakpointObserver, parentSnackBar: MatSnackBar, defaultConfig: MatSnackBarConfig);
54+
// (undocumented)
5555
protected handsetCssClass: string;
5656
// (undocumented)
57-
ngOnDestroy(): void;
58-
open(message: string, action?: string, config?: MatSnackBarConfig): MatSnackBarRef<TextOnlySnackBar>;
59-
get _openedSnackBarRef(): MatSnackBarRef<any> | null;
60-
set _openedSnackBarRef(value: MatSnackBarRef<any> | null);
61-
openFromComponent<T>(component: ComponentType<T>, config?: MatSnackBarConfig): MatSnackBarRef<T>;
62-
openFromTemplate(template: TemplateRef<any>, config?: MatSnackBarConfig): MatSnackBarRef<EmbeddedViewRef<any>>;
63-
protected simpleSnackBarComponent: Type<TextOnlySnackBar>;
64-
protected snackBarContainerComponent: Type<_SnackBarContainer>;
57+
protected simpleSnackBarComponent: typeof SimpleSnackBar;
58+
// (undocumented)
59+
protected snackBarContainerComponent: typeof MatSnackBarContainer;
6560
// (undocumented)
6661
static ɵfac: i0.ɵɵFactoryDeclaration<MatSnackBar, [null, null, null, null, { optional: true; skipSelf: true; }, null]>;
6762
// (undocumented)
@@ -73,6 +68,26 @@ export const matSnackBarAnimations: {
7368
readonly snackBarState: AnimationTriggerMetadata;
7469
};
7570

71+
// @public (undocumented)
72+
export abstract class _MatSnackBarBase implements OnDestroy {
73+
constructor(_overlay: Overlay, _live: LiveAnnouncer, _injector: Injector, _breakpointObserver: BreakpointObserver, _parentSnackBar: _MatSnackBarBase, _defaultConfig: MatSnackBarConfig);
74+
dismiss(): void;
75+
protected abstract handsetCssClass: string;
76+
// (undocumented)
77+
ngOnDestroy(): void;
78+
open(message: string, action?: string, config?: MatSnackBarConfig): MatSnackBarRef<TextOnlySnackBar>;
79+
get _openedSnackBarRef(): MatSnackBarRef<any> | null;
80+
set _openedSnackBarRef(value: MatSnackBarRef<any> | null);
81+
openFromComponent<T>(component: ComponentType<T>, config?: MatSnackBarConfig): MatSnackBarRef<T>;
82+
openFromTemplate(template: TemplateRef<any>, config?: MatSnackBarConfig): MatSnackBarRef<EmbeddedViewRef<any>>;
83+
protected abstract simpleSnackBarComponent: Type<TextOnlySnackBar>;
84+
protected abstract snackBarContainerComponent: Type<_SnackBarContainer>;
85+
// (undocumented)
86+
static ɵfac: i0.ɵɵFactoryDeclaration<_MatSnackBarBase, [null, null, null, null, { optional: true; skipSelf: true; }, null]>;
87+
// (undocumented)
88+
static ɵprov: i0.ɵɵInjectableDeclaration<_MatSnackBarBase>;
89+
}
90+
7691
// @public
7792
export class MatSnackBarConfig<D = any> {
7893
announcementMessage?: string;

0 commit comments

Comments
 (0)