Angular 材质 Snackbar 配置与自定义 panelClass 配置,用于错误、成功、警告消息
Posted
技术标签:
【中文标题】Angular 材质 Snackbar 配置与自定义 panelClass 配置,用于错误、成功、警告消息【英文标题】:Angular material Snackbar configuration with custom panelClass configuration for error, success, warning messages 【发布时间】:2020-09-10 03:06:35 【问题描述】:我在我的 Angular 应用程序中创建了一个全局的snackBarService。我想根据消息类型(错误、成功、警告等)自定义panelClass
。我采用的方法是在构造函数中进行全局配置,这有助于为小吃店定义全局样式/配置,并将添加自定义类以根据消息类型更改背景颜色。
SnackBarService.ts
import Injectable, NgZone from "@angular/core";
import MatSnackBar, MatSnackBarConfig from "@angular/material";
@Injectable(
providedIn: "root",
)
export class SnackbarService
private config: MatSnackBarConfig;
constructor(private snackbar: MatSnackBar, private zone: NgZone)
this.config = new MatSnackBarConfig();
this.config.panelClass = ["snackbar-container"];
this.config.verticalPosition = "top";
this.config.horizontalPosition = "right";
this.config.duration = 4000;
error(message: string)
this.config.panelClass = ["snackbar-container", "error"];
this.show(message);
success(message: string)
this.config.panelClass = ["snackbar-container", "success"];
this.show(message);
warning(message: string)
this.config.panelClass = ["snackbar-container", "warning"];
this.show(message);
private show(message: string, config?: MatSnackBarConfig)
config = config || this.config;
this.zone.run(() =>
this.snackbar.open(message, "x", config);
);
app.scss
.snackbar-container
margin-top: 70px !important;
color: beige;
&.error
background-color: #c62828 !important;
&.success
background-color: #2e7d32 !important;
&.warning
background-color: #ff8f00 !important;
从组件中我将使用这样的服务
this.snackbarService.success("This message is from snackbar!!!");
以上代码完美运行。
但是,
由于panelClass
没有.push
方法,我无法添加动态类,因此我每次都需要像this.config.panelClass = ["snackbar-container", "error"];
这样复制全局类
error(message: string)
this.config.panelClass.push("error"); // this throws error in typescript
this.show(message);
有没有更好的方法来解决这个问题?
【问题讨论】:
【参考方案1】:Angular Material 实际上为您提供了一种设置默认配置的本地方式,因此您无需实例化 MatSnackBarConfig 然后设置其值。在您导入 MatSnackBarModule 的模块(App/Shared/Material 模块)中,添加以下内容:
import MatSnackBarModule, MatSnackBarConfig, MAT_SNACK_BAR_DEFAULT_OPTIONS from '@angular/material/snack-bar';
const matSnackbarDefaultConfig: MatSnackBarConfig =
verticalPosition: 'top',
horizontalPosition: 'right',
duration: 4000,
;
@NgModule(
// ...
providers: [
provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
useValue: matSnackbarDefaultConfig,
,
],
)
export class MaterialModule
然后,您可以像这样使用您的服务(我添加了更多的输入内容,如果您不喜欢它并且不使用 strictNullChecks,请随时删除它们):
import Injectable, NgZone from '@angular/core';
import MatSnackBar, MatSnackBarConfig from '@angular/material/snack-bar';
// I actually recommend that you put this in a utils/helpers folder so you can use reuse it whenever needed
export const coerceToArray = <T>(value: T | T[]): T[] => (
Array.isArray(value)
? value
: [value]
);
@Injectable(
providedIn: 'root',
)
export class SnackbarService
constructor(private snackbar: MatSnackBar, private zone: NgZone)
error(message: string): void
this.show(message, panelClass: ['snackbar-container', 'error'] );
success(message: string): void
this.show(message, panelClass: ['snackbar-container', 'success'] );
warning(message: string): void
this.show(message, panelClass: ['snackbar-container', 'warning'] );
private show(message: string, customConfig: MatSnackBarConfig = ): void
const customClasses = coerceToArray(customConfig.panelClass)
.filter((v) => typeof v === 'string') as string[];
this.zone.run(() =>
this.snackbar.open(
message,
'x',
...customConfig, panelClass: ['snackbar-container', ...customClasses] ,
);
);
此外,由于您的公共方法不接受其他配置来传递(例如持续时间),您可以将您的服务减少到:
import Injectable, NgZone from '@angular/core';
import MatSnackBar from '@angular/material/snack-bar';
// Just add the new required types here and TypeScript will require the public consumer to pass a valid type
export type SnackBarType = 'error' | 'success' | 'warning';
@Injectable(
providedIn: 'root',
)
export class SnackbarService
constructor(private snackbar: MatSnackBar, private zone: NgZone)
show(message: string, type: SnackBarType): void
this.zone.run(() =>
this.snackbar.open(
message,
'x',
panelClass: ['snackbar-container', type] ,
);
);
【讨论】:
【参考方案2】:你可以这样做:
(this.config.panelClass as string[]).push('error');
但是您将添加类而不删除已经存在的类。您仍然需要每次使用初始类重置数组:
this.config.panelClass = ['snackbar-container']
【讨论】:
以上是关于Angular 材质 Snackbar 配置与自定义 panelClass 配置,用于错误、成功、警告消息的主要内容,如果未能解决你的问题,请参考以下文章
Angular (v5+) - Snackbar “openFromComponent”,组件通信
Angular Material Snackbar 未正确显示