Skip to content

Commit bdb649a

Browse files
committed
fix(material-experimental/mdc-snack-bar): avoid hard reference to base components and align API
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.
1 parent 0742bab commit bdb649a

File tree

10 files changed

+89
-40
lines changed

10 files changed

+89
-40
lines changed

scripts/check-mdc-exports-config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export const config = {
2020
'MAT_SLIDER_VALUE_ACCESSOR',
2121
// Irrelevant for the MDC implementation, because the slider doesn't dispatch any events.
2222
'MatSliderChange'
23+
],
24+
'mdc-snack-bar': [
25+
// TODO: needs to be renamed to match the non-MDC version.
26+
'SimpleSnackBar'
2327
]
2428
}
2529
};

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

Lines changed: 2 additions & 3 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',
@@ -22,7 +22,6 @@ import {
2222
encapsulation: ViewEncapsulation.None,
2323
})
2424
export class MdcSnackBarDemo {
25-
2625
@ViewChild('template') template: TemplateRef<any>;
2726
message = 'Snack Bar opened.';
2827
actionButtonLabel = 'Retry';

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

Lines changed: 1 addition & 1 deletion
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 {MatSimpleSnackBar} from './public-api';
1717
import {MatSnackBarContainer} from './snack-bar-container';
1818
import {
1919
MatSnackBarAction,

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: 6 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',
@@ -27,7 +22,7 @@ import {
2722
})
2823
export class MatSimpleSnackBar implements TextOnlySnackBar {
2924
constructor(
30-
public snackBarRef: MatSnackBarRef<SimpleSnackBar>,
25+
public snackBarRef: MatSnackBarRef<MatSimpleSnackBar>,
3126
@Inject(MAT_SNACK_BAR_DATA) public data: {message: string, action: string}) {
3227
}
3328

@@ -42,3 +37,6 @@ export class MatSimpleSnackBar implements TextOnlySnackBar {
4237
}
4338
}
4439

40+
// For backwards compatibility.
41+
// tslint:disable-next-line:variable-name
42+
export const SimpleSnackBar = MatSimpleSnackBar;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ describe('MatSnackBar', () => {
217217
viewContainerFixture.detectChanges();
218218

219219
expect(snackBarRef.instance instanceof MatSimpleSnackBar)
220-
.toBe(true, 'Expected the snack bar content component to be SimpleSnackBar');
220+
.toBe(true, 'Expected the snack bar content component to be MatSimpleSnackBar');
221221
expect(snackBarRef.instance.snackBarRef)
222222
.toBe(snackBarRef,
223223
'Expected the snack bar reference to be placed in the component instance');
@@ -241,7 +241,7 @@ describe('MatSnackBar', () => {
241241
viewContainerFixture.detectChanges();
242242

243243
expect(snackBarRef.instance instanceof MatSimpleSnackBar)
244-
.toBe(true, 'Expected the snack bar content component to be SimpleSnackBar');
244+
.toBe(true, 'Expected the snack bar content component to be MatSimpleSnackBar');
245245
expect(snackBarRef.instance.snackBarRef)
246246
.toBe(snackBarRef,
247247
'Expected the snack bar reference to be placed in the component instance');

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

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,15 @@
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';
1219
import {MatSimpleSnackBar} from './simple-snack-bar';
1320
import {MatSnackBarContainer} from './snack-bar-container';
@@ -16,8 +23,18 @@ import {MatSnackBarContainer} from './snack-bar-container';
1623
* Service to dispatch Material Design snack bar messages.
1724
*/
1825
@Injectable({providedIn: MatSnackBarModule})
19-
export class MatSnackBar extends BaseMatSnackBar {
26+
export class MatSnackBar extends _MatSnackBarBase {
2027
protected override simpleSnackBarComponent = MatSimpleSnackBar;
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+
super(overlay, live, injector, breakpointObserver, parentSnackBar, defaultConfig);
39+
}
2340
}

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
@@ -3,5 +3,5 @@ import {runHarnessTests} from '@angular/material/snack-bar/testing/shared.spec';
33
import {MatSnackBarHarness} from './snack-bar-harness';
44

55
describe('MDC-based MatSnackBarHarness', () => {
6-
runHarnessTests(MatSnackBarModule, MatSnackBar, MatSnackBarHarness as any);
6+
runHarnessTests(MatSnackBarModule, MatSnackBar as any, MatSnackBarHarness as any);
77
});

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

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,8 @@ export function MAT_SNACK_BAR_DEFAULT_OPTIONS_FACTORY(): MatSnackBarConfig {
4242
return new MatSnackBarConfig();
4343
}
4444

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

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

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

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

6663
/** Reference to the currently opened snackbar at *any* level. */
6764
get _openedSnackBarRef(): MatSnackBarRef<any> | null {
@@ -82,8 +79,8 @@ export class MatSnackBar implements OnDestroy {
8279
private _live: LiveAnnouncer,
8380
private _injector: Injector,
8481
private _breakpointObserver: BreakpointObserver,
85-
@Optional() @SkipSelf() private _parentSnackBar: MatSnackBar,
86-
@Inject(MAT_SNACK_BAR_DEFAULT_OPTIONS) private _defaultConfig: MatSnackBarConfig) {}
82+
private _parentSnackBar: _MatSnackBarBase,
83+
private _defaultConfig: MatSnackBarConfig) {}
8784

8885
/**
8986
* Creates and dispatches a snack bar with a custom component for the content, removing any
@@ -300,3 +297,23 @@ export class MatSnackBar implements OnDestroy {
300297
});
301298
}
302299
}
300+
301+
/**
302+
* Service to dispatch Material Design snack bar messages.
303+
*/
304+
@Injectable({providedIn: MatSnackBarModule})
305+
export class MatSnackBar extends _MatSnackBarBase {
306+
protected simpleSnackBarComponent = SimpleSnackBar;
307+
protected snackBarContainerComponent = MatSnackBarContainer;
308+
protected handsetCssClass = 'mat-snack-bar-handset';
309+
310+
constructor(
311+
overlay: Overlay,
312+
live: LiveAnnouncer,
313+
injector: Injector,
314+
breakpointObserver: BreakpointObserver,
315+
@Optional() @SkipSelf() parentSnackBar: MatSnackBar,
316+
@Inject(MAT_SNACK_BAR_DEFAULT_OPTIONS) defaultConfig: MatSnackBarConfig) {
317+
super(overlay, live, injector, breakpointObserver, parentSnackBar, defaultConfig);
318+
}
319+
}

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, never>;
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)