【问题标题】:How to use SnackBar on service to use in every component in Angular 2如何在服务上使用 SnackBar 以在 Angular 2 中的每个组件中使用
【发布时间】:2017-08-03 07:35:07
【问题描述】:

我有一个可以工作的小吃店,但它只在每个组件上,我想将它添加到我的服务中,所以我将调用它。这是我在component.ts 上的示例

import { MdSnackBar, MdSnackBarRef } from '@angular/material';
...
export class EmployeeListComponent implements OnInit {
  public toastRef: MdSnackBarRef<any>;
  constructor(private _activatedRoute:ActivatedRoute,private router: Router, private http:PMISHttpService, private toast: MdSnackBar) {

  ngOnInit() {
    this.notify('test');
  }
  ...
  notify (text: string) {
    this.toastRef = this.toast.open(text, null);
    setTimeout(() => {
      this.toastRef.dismiss();
    }, 5000);
  }
  ...
}

【问题讨论】:

    标签: angular angular-material2 snackbar


    【解决方案1】:

    如果您希望 SnackBar 在您的整个应用程序中工作,您应该将其放入您的 app.component 并通过服务与其通信。

    notification.service.ts:

    public notification$: Subject<string> = new Subject();
    

    app.component.ts:

    constructor(
      private notificationService: NotificationService, private snackBar: MatSnackBar
    ) {
      this.notificationService.notification$.subscribe(message => {
        this.snackBar.open(message);
      });
    }
    

    任何.component.ts:

    this.notificationService.notification$.next('this is a notification');
    

    【讨论】:

    • 通知功能放在哪里?对不起,我是新手
    • 你创建了一个全局服务,它有一个 'subj_notification' rxjs 主题,你的 app.component 有snackBar 并且订阅了'subj_notification'。此时,您应用中的任何组件都可以调用服务的 subj_notification.next() 并且您的应用组件将收到主题更改的通知。
    【解决方案2】:

    要让它无处不在,请为它创建一个服务。你也应该使用snackbar config来设置持续时间并将snackbar公开:

    import {Injectable, NgZone} from '@angular/core';
    import {MatSnackBar} from '@angular/material';
    
    @Injectable()
    export class CustomSnackbarService {
    
        constructor(
          public snackBar: MatSnackBar,
          private zone: NgZone
        ) {}
    
        public open(message, action = 'success', duration = 50000) {
            this.zone.run(() => {
                this.snackBar.open(message, action, { duration });
            });
        }
    }
    

    还需要在ngZone:https://github.com/angular/material2/issues/9875中运行

    然后在组件中:

    customSnackbarService.open('hello')

    【讨论】:

    • 这对我很有用!我只是做了一个小修改,让调用者可以访问 SnackBarRef: return this.zone.run(() => { return this.snackBar.open(message, action, { duration }); });跨度>
    • 有意思,zone.run 是否返回内部函数?
    • 不确定是否仍需要 NgZone。我试过没有,代码似乎仍然可以工作(使用 Angular 10)。无论如何,感谢您的解决方案!
    • 很有可能
    【解决方案3】:

    您可以轻松做到这一点。请在下面找到我在我的一个项目中使用的示例的示例,它工作得很好

    import { Injectable } from '@angular/core';
    import {
      MatSnackBar,
      MatSnackBarConfig,
      MatSnackBarHorizontalPosition,
      MatSnackBarVerticalPosition,
      MatSnackBarRef
    } from '@angular/material';
    
    @Injectable()
    export class SnackBarService {
    
      snackBarConfig: MatSnackBarConfig;
      snackBarRef: MatSnackBarRef<any>;
      horizontalPosition: MatSnackBarHorizontalPosition = 'center';
      verticalPosition: MatSnackBarVerticalPosition = 'top';
      snackBarAutoHide = '1500';
    
      constructor(private snackBar: MatSnackBar) { }
    
      openSnackBar(message) {
        this.snackBarConfig = new MatSnackBarConfig();
        this.snackBarConfig.horizontalPosition = this.horizontalPosition;
        this.snackBarConfig.verticalPosition = this.verticalPosition;
        this.snackBarConfig.duration = parseInt(this.snackBarAutoHide, 0);
        this.snackBarConfig.panelClass = 'custom-snackbar';
        this.snackBarRef = this.snackBar.open(message, '', this.snackBarConfig);
    }
    
    }
    

    现在,你只需要在你的组件或者你想使用它的地方注入这个服务,然后调用 openSnackBar() 方法来显示你想要显示的消息。

    希望这会有所帮助!

    【讨论】:

    • 简单明了的答案
    【解决方案4】:

    这是我的工作示例(Angular 11,Angular Material 11.0.1)。

    最重要的部分是在 app.module.ts 中包含 MatSnackBarModule。另外,不要忘记导入 BrowserAnimationsModule

    import { MatSnackBarModule } from '@angular/material/snack-bar';
    import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    
    @NgModule({
      imports: [
        MatSnackBarModule,
        BrowserAnimationsModule
        ...
      ],
    

    那么,我的服务是这样的

    import { Injectable } from '@angular/core';
    import { MatSnackBar } from '@angular/material/snack-bar';
    
    @Injectable({
      providedIn: 'root'
    })
    export class SnackbarService {
    
      constructor(
        private _snackBar: MatSnackBar) {
      }
    
      error(message: string) {
        return this._snackBar.open(message, undefined, {panelClass: ['snackbar-error']});
      }
    
      success(message: string) {
        return this._snackBar.open(message, undefined, {panelClass: ['snackbar-success']});
      }
    
      info(message: string) {
        return this._snackBar.open(message, undefined, {panelClass: ['snackbar-info']});
      }
    }
    
    

    为了定义样式,我将这些添加到 styles.scss

    .mat-simple-snackbar {
      font-size: 1.2em;
      color: white;
    }
    
    .snackbar-error {
      background-color: red;
    }
    
    .snackbar-success {
      background-color: green;
    }
    
    .snackbar-info {
      background-color: blue;
    }
    
    

    这样,我现在可以从代码中的任何位置(包括来自其他模块的组件)调用 SnackBar。使用示例:

    import { Component } from '@angular/core';
    import { AuthService } from 'src/app/services/auth/auth.service';
    import { SnackbarService } from 'src/app/services/snackbar.service';
    
    @Component({
      selector: 'app-login',
      templateUrl: './login.component.html',
      styleUrls: ['./login.component.scss']
    })
    export class LoginComponent {
    
      loginForm: any;
    
      constructor(private authService: AuthService, private snackbar: SnackbarService) { }
    
      onSubmit() {
          this.authService.login(this.loginForm).subscribe(res => {
            this.snackbar.success('Logged in');
          }, e => {
            this.snackbar.error('Login failed');
          });
      }
    
    }
    
    

    【讨论】:

    • 与 Angular 10 和 Angular Material 完美配合 ^10.2.7 您可以升级具有额外属性的小吃栏,例如 5 秒后消失,或者将酒吧从下到上重新定位,如下所示:error(message: string) { return this._snackBar.open(message, null, { duration: 5000, verticalPosition: 'top', horizontalPosition: 'center', panelClass: ['snackbar-error'] }); }
    • 很好的答案,你应该使用undefined 而不是null
    • @andrèscoronado 为什么是undefined
    • @TomasLukac typescript (method) MatSnackBar.open(message: string, action?: string | undefined, config?: MatSnackBarConfig&lt;any&gt; | undefined): MatSnackBarRef&lt;TextOnlySnackBar&gt;
    • @TomasLukac 的非常好的和简单的回答我添加了额外的参数来自动关闭小吃店{ panelClass: ['snackbar-info'], duration: 5000 }
    【解决方案5】:

    我正在使用版本 version": "2.0.0-beta.10", 这就是我为使其正常工作所做的工作

    在 ApModule 中

    import { NotificationService } from "./notification/notification.service";
    import { MdSnackBarModule } from "@angular/material";
    
    @NgModule({
      imports: [
        MdSnackBarModule,
        FormsModule
      ],
      providers: [WebService, NotificationService]
    

    按照上一篇文章的建议创建通知服务

    import { Injectable } from "@angular/core";
    import {
      MdSnackBar,
      MdSnackBarConfig,
      // MdSnackBarHorizontalPosition,
      // MdSnackBarVerticalPosition,
      MdSnackBarRef
    } from "@angular/material";
    
    @Injectable()
    export class NotificationService {
      private snackBarConfig: MdSnackBarConfig;
      private snackBarRef: MdSnackBarRef<any>;
        private snackBarAutoHide = "5000"; //milliseconds for notification , 5 secs
    
      constructor(private sb: MdSnackBar) {}
    
      openSnackBar(message) {
        this.snackBarConfig = new MdSnackBarConfig();
        //this.snackBarConfig.horizontalPosition = this.horizontalPosition; only in current version Demo uses very old version . need to upgrade later
        //this.snackBarConfig.verticalPosition = this.verticalPosition; only in current version Demo uses very old version . need to upgrade later
        this.snackBarConfig.duration = parseInt(this.snackBarAutoHide, 0);
          this.sb.open(message, "", this.snackBarConfig);
      }
    }
    

    如下图消费服务

       this.notify.openSnackBar(message);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-18
      • 1970-01-01
      • 2016-03-30
      • 2017-10-25
      • 2016-09-19
      • 2018-02-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多