mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(snack-bar): add injection token for overriding the default options (#9849)
Adds the `MAT_SNACK_BAR_DEFAULT_OPTIONS` injection token that allows consumers to set the default snack bar options globally. Fixes #9821.
This commit is contained in:
committed by
tinayuangao
parent
ccbab877c3
commit
a943b36c7b
@@ -13,11 +13,17 @@ import {PortalModule} from '@angular/cdk/portal';
|
||||
import {LIVE_ANNOUNCER_PROVIDER} from '@angular/cdk/a11y';
|
||||
import {LayoutModule} from '@angular/cdk/layout';
|
||||
import {MatCommonModule} from '@angular/material/core';
|
||||
import {MatSnackBar} from './snack-bar';
|
||||
import {MatSnackBar, MAT_SNACK_BAR_DEFAULT_OPTIONS} from './snack-bar';
|
||||
import {MatSnackBarContainer} from './snack-bar-container';
|
||||
import {MatSnackBarConfig} from './snack-bar-config';
|
||||
import {SimpleSnackBar} from './simple-snack-bar';
|
||||
|
||||
|
||||
/** @docs-private */
|
||||
export function MAT_SNACK_BAR_DEFAULT_OPTIONS_PROVIDER_FACTORY() {
|
||||
return new MatSnackBarConfig();
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
OverlayModule,
|
||||
@@ -29,6 +35,13 @@ import {SimpleSnackBar} from './simple-snack-bar';
|
||||
exports: [MatSnackBarContainer, MatCommonModule],
|
||||
declarations: [MatSnackBarContainer, SimpleSnackBar],
|
||||
entryComponents: [MatSnackBarContainer, SimpleSnackBar],
|
||||
providers: [MatSnackBar, LIVE_ANNOUNCER_PROVIDER]
|
||||
providers: [
|
||||
MatSnackBar,
|
||||
LIVE_ANNOUNCER_PROVIDER,
|
||||
{
|
||||
provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
|
||||
useFactory: MAT_SNACK_BAR_DEFAULT_OPTIONS_PROVIDER_FACTORY
|
||||
},
|
||||
]
|
||||
})
|
||||
export class MatSnackBarModule {}
|
||||
|
||||
@@ -72,6 +72,19 @@ export class MessageArchivedComponent {
|
||||
constructor(@Inject(MAT_SNACK_BAR_DATA) public data: any) { }
|
||||
}
|
||||
```
|
||||
|
||||
### Setting the global configuration defaults
|
||||
If you want to override the default snack bar options, you can do so using the
|
||||
`MAT_SNACK_BAR_DEFAULT_OPTIONS` injection token.
|
||||
|
||||
```ts
|
||||
@NgModule({
|
||||
providers: [
|
||||
{provide: MAT_SNACK_BAR_DEFAULT_OPTIONS, useValue: {duration: 2500}}
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
### Accessibility
|
||||
Snack-bar messages are announced via an `aria-live` region. Focus is not moved to
|
||||
the snack-bar element, as this would be disruptive to a user in the middle of a
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
MatSnackBarRef,
|
||||
SimpleSnackBar,
|
||||
MAT_SNACK_BAR_DATA,
|
||||
MAT_SNACK_BAR_DEFAULT_OPTIONS,
|
||||
} from './index';
|
||||
|
||||
describe('MatSnackBar', () => {
|
||||
@@ -387,6 +388,32 @@ describe('MatSnackBar', () => {
|
||||
expect(pane.getAttribute('dir')).toBe('rtl', 'Expected the pane to be in RTL mode.');
|
||||
});
|
||||
|
||||
it('should be able to override the default config', fakeAsync(() => {
|
||||
overlayContainer.ngOnDestroy();
|
||||
viewContainerFixture.destroy();
|
||||
|
||||
TestBed
|
||||
.resetTestingModule()
|
||||
.overrideProvider(MAT_SNACK_BAR_DEFAULT_OPTIONS, {
|
||||
deps: [],
|
||||
useFactory: () => ({panelClass: 'custom-class'})
|
||||
})
|
||||
.configureTestingModule({imports: [MatSnackBarModule, NoopAnimationsModule]})
|
||||
.compileComponents();
|
||||
|
||||
inject([MatSnackBar, OverlayContainer], (sb: MatSnackBar, oc: OverlayContainer) => {
|
||||
snackBar = sb;
|
||||
overlayContainer = oc;
|
||||
overlayContainerElement = oc.getContainerElement();
|
||||
})();
|
||||
|
||||
snackBar.open(simpleMessage);
|
||||
flush();
|
||||
|
||||
expect(overlayContainerElement.querySelector('snack-bar-container')!.classList)
|
||||
.toContain('custom-class', 'Expected class applied through the defaults to be applied.');
|
||||
}));
|
||||
|
||||
describe('with custom component', () => {
|
||||
it('should open a custom component', () => {
|
||||
const snackBarRef = snackBar.openFromComponent(BurritosNotification);
|
||||
@@ -504,7 +531,6 @@ describe('MatSnackBar with parent MatSnackBar', () => {
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
describe('MatSnackBar Positioning', () => {
|
||||
let snackBar: MatSnackBar;
|
||||
let liveAnnouncer: LiveAnnouncer;
|
||||
|
||||
@@ -10,7 +10,15 @@ import {LiveAnnouncer} from '@angular/cdk/a11y';
|
||||
import {BreakpointObserver, Breakpoints} from '@angular/cdk/layout';
|
||||
import {Overlay, OverlayConfig, OverlayRef} from '@angular/cdk/overlay';
|
||||
import {ComponentPortal, ComponentType, PortalInjector} from '@angular/cdk/portal';
|
||||
import {ComponentRef, Injectable, Injector, Optional, SkipSelf} from '@angular/core';
|
||||
import {
|
||||
ComponentRef,
|
||||
Inject,
|
||||
Injectable,
|
||||
Injector,
|
||||
InjectionToken,
|
||||
Optional,
|
||||
SkipSelf,
|
||||
} from '@angular/core';
|
||||
import {take} from 'rxjs/operators/take';
|
||||
import {takeUntil} from 'rxjs/operators/takeUntil';
|
||||
import {SimpleSnackBar} from './simple-snack-bar';
|
||||
@@ -19,6 +27,10 @@ import {MatSnackBarContainer} from './snack-bar-container';
|
||||
import {MatSnackBarRef} from './snack-bar-ref';
|
||||
|
||||
|
||||
/** Injection token that can be used to specify default snack bar. */
|
||||
export const MAT_SNACK_BAR_DEFAULT_OPTIONS =
|
||||
new InjectionToken<MatSnackBarConfig>('mat-snack-bar-default-options');
|
||||
|
||||
/**
|
||||
* Service to dispatch Material Design snack bar messages.
|
||||
*/
|
||||
@@ -50,7 +62,8 @@ export class MatSnackBar {
|
||||
private _live: LiveAnnouncer,
|
||||
private _injector: Injector,
|
||||
private _breakpointObserver: BreakpointObserver,
|
||||
@Optional() @SkipSelf() private _parentSnackBar: MatSnackBar) {}
|
||||
@Optional() @SkipSelf() private _parentSnackBar: MatSnackBar,
|
||||
@Inject(MAT_SNACK_BAR_DEFAULT_OPTIONS) private _defaultConfig: MatSnackBarConfig) {}
|
||||
|
||||
/**
|
||||
* Creates and dispatches a snack bar with a custom component for the content, removing any
|
||||
@@ -60,7 +73,7 @@ export class MatSnackBar {
|
||||
* @param config Extra configuration for the snack bar.
|
||||
*/
|
||||
openFromComponent<T>(component: ComponentType<T>, config?: MatSnackBarConfig): MatSnackBarRef<T> {
|
||||
const _config = _applyConfigDefaults(config);
|
||||
const _config = {...this._defaultConfig, ...config};
|
||||
const snackBarRef = this._attach(component, _config);
|
||||
|
||||
// When the snackbar is dismissed, clear the reference to it.
|
||||
@@ -104,7 +117,7 @@ export class MatSnackBar {
|
||||
*/
|
||||
open(message: string, action: string = '', config?: MatSnackBarConfig):
|
||||
MatSnackBarRef<SimpleSnackBar> {
|
||||
const _config = _applyConfigDefaults(config);
|
||||
const _config = {...this._defaultConfig, ...config};
|
||||
|
||||
// Since the user doesn't have access to the component, we can
|
||||
// override the data to pass in our own message and action.
|
||||
@@ -216,12 +229,3 @@ export class MatSnackBar {
|
||||
return new PortalInjector(userInjector || this._injector, injectionTokens);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies default options to the snackbar config.
|
||||
* @param config The configuration to which the defaults will be applied.
|
||||
* @returns The new configuration object with defaults applied.
|
||||
*/
|
||||
function _applyConfigDefaults(config?: MatSnackBarConfig): MatSnackBarConfig {
|
||||
return {...new MatSnackBarConfig(), ...config};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user