Sar*_*air 3 javascript angular-material snackbar 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);
});
}
}
Run Code Online (Sandbox Code Playgroud)
应用程序.scss
.snackbar-container {
margin-top: 70px !important;
color: beige;
&.error {
background-color: #c62828 !important;
}
&.success {
background-color: #2e7d32 !important;
}
&.warning {
background-color: #ff8f00 !important;
}
}
Run Code Online (Sandbox Code Playgroud)
从组件中我将使用这样的服务
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);
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来解决这个问题呢?
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 { }
Run Code Online (Sandbox Code Playgroud)
然后,您可以像这样使用您的服务(我添加了更多的输入内容,如果您不喜欢它并且不使用 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] },
);
});
}
}
Run Code Online (Sandbox Code Playgroud)
另外,由于您的公共方法不接受其他传递配置(例如持续时间),因此您可以将服务减少为:
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] },
);
});
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5018 次 |
| 最近记录: |