Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 角度2/4-材料设计快捷键按顺序显示多条信息_Javascript_Angular_Angular Material - Fatal编程技术网

Javascript 角度2/4-材料设计快捷键按顺序显示多条信息

Javascript 角度2/4-材料设计快捷键按顺序显示多条信息,javascript,angular,angular-material,Javascript,Angular,Angular Material,我已经实现了一个“snackbar服务”,它显示: snackbar.service.ts 但所有消息同时显示(重叠) 如何等待快捷键将新消息显示到messageQueue中?您可以通过进行以下简单更改来实现这一点: this.snackBarService.add(['A','B','C']); // pass messages as array add(messages: Array<string>, action?: string, config?: MdSnackBarCo

我已经实现了一个“snackbar服务”,它显示:

snackbar.service.ts

但所有消息同时显示(重叠)


如何等待快捷键将新消息显示到messageQueue中?

您可以通过进行以下简单更改来实现这一点:

this.snackBarService.add(['A','B','C']); // pass messages as array

add(messages: Array<string>, action?: string, config?: MdSnackBarConfig): void{
    if ( !config ){
        config = new MdSnackBarConfig();
        config.duration = 10000;
    }

    let sbMessage = new SnackBarMessage();
    sbMessage.message = message;
    sbMessage.action = action;
    sbMessage.config = config;

    messages.forEach((message,index) => {
        setTimeout((message) => {
            sbMessage.message = message;
            this.messageQueue.next(sbMessage);
        },(config.duration*index);
    })
}
this.snackBarService.add(['A','B','C']);//以数组形式传递消息
添加(消息:数组,操作?:字符串,配置?:MdSnackBarConfig):无效{
如果(!config){
config=new MdSnackBarConfig();
config.duration=10000;
}
让sbMessage=newsnackbarmessage();
sbMessage.message=消息;
sbMessage.action=操作;
sbMessage.config=config;
messages.forEach((消息,索引)=>{
设置超时((消息)=>{
sbMessage.message=消息;
this.messageQueue.next(sbMessage);
},(配置持续时间*索引);
})
}

您需要使用超时方法。 在特定时间内隐藏snackbar,并使用超时功能打开另一个snackbar

constructor(public snackBarService: SnackBarService) {
          this.snackBarService.add('A')
          setTimeout(this.snackBarService.add('B'),10000);
          setTimeout(this.snackBarService.add('C'),20000);
       }

正如@Aamir Khan所指出的,我使用了
afterdismised
,对您的代码进行了一些调整

  showNext() {
  if (this.msgQueue === 0) {
    return;
  }

  let message = this.msgQueue.shift();
  this.isInstanceVisible = true;
  this.snackBarRef = this.snackBar.open(message.message, message.action, {duration: 2000});
  this.snackBarRef.afterDismissed().subscribe(() => {
    this.isInstanceVisible = false;
    this.showNext();
  });
}
add()中添加了这个-

this.msgQueue.push(sbMessage);
if (!this.isInstanceVisible) {
     this.showNext(); 
}


注意-这是一种肮脏的非标准方式,不是理想的用户体验(IMO),由于使用了标志,上述代码可能会有一些内存泄漏和竞争条件。

这里是@Ankit's Plunker

import {Subscription} from 'rxjs';
import {Injectable, OnDestroy} from '@angular/core';
import {MatSnackBar, MatSnackBarConfig} from '@angular/material/snack-bar';
import {MatSnackBarRef, SimpleSnackBar} from '@angular/material/snack-bar';
import {SnackBarMessage} from './snackBarMessage.model';

@Injectable()
export class NotificationService implements OnDestroy {
  private messageQueue: Array<any> = Array<any>();
  private subscription: Subscription;
  private snackBarRef: MatSnackBarRef<SimpleSnackBar>;
  private isInstanceVisible = false;

  constructor(public snackBar: MatSnackBar) {}

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
  /**
   * Add a message
   * @param message The message to show in the snackbar.
   * @param action The label for the snackbar action.
   * @param config Additional configuration options for the snackbar.
   * @param classOverride Adds a css class on the snackbar so you can add color.

   */
  show(
    message: string,
    action?: string,
    config?: MatSnackBarConfig,
    classOverride: string = 'blue-snackbar'
  ): void {
    if (!config) {
      config = new MatSnackBarConfig();
      config.duration = 3000;
      config.verticalPosition = 'bottom';
      config.horizontalPosition = 'end';
      config.panelClass = [classOverride];
    }

    const sbMessage = new SnackBarMessage();
    sbMessage.message = message;
    sbMessage.action = action;
    sbMessage.config = config;

    this.messageQueue.push(sbMessage);

    if (!this.isInstanceVisible) {
      this.showNext();
    }
  }

  private showNext() {
    if (this.messageQueue.length === 0) {
      return;
    }

    const message = this.messageQueue.shift();
    this.isInstanceVisible = true;

    this.snackBarRef = this.snackBar.open(
      message.message,
      message.action,
      message.config
    );

    this.snackBarRef.afterDismissed().subscribe(() => {
      this.isInstanceVisible = false;
      this.showNext();
    });
  }
}
从'rxjs'导入{Subscription};
从“@angular/core”导入{Injectable,OnDestroy};
从“@angular/material/snakp bar”导入{matsnakbar,matsnakbarconfig};
从“@angular/material/snakp bar”导入{matsnakbaref,simplesnakbar};
从“./SnackBarMessage.model”导入{SnackBarMessage};
@可注射()
导出类NotificationService实现OnDestroy{
private messageQueue:Array=Array();
私人认购:认购;
私人小吃架:Matsnakbarref;
private isInstanceVisible=false;
构造函数(公共snackBar:matsnakbar){}
恩贡德斯特罗(){
this.subscription.unsubscripte();
}
/**
*添加消息
*@param message要在snackbar中显示的消息。
*@param action snackbar操作的标签。
*@param config snackbar的其他配置选项。
*@param classOverride在snackbar上添加了一个css类,因此您可以添加颜色。
*/
展示(
消息:string,
动作?:字符串,
配置?:MatsnakBarConfig,
classOverride:string='blue snackbar'
):无效{
如果(!config){
config=new matsnakbarconfig();
config.duration=3000;
config.verticalPosition='bottom';
config.horizontalPosition='end';
config.panelClass=[classOverride];
}
const sbMessage=new SnackBarMessage();
sbMessage.message=消息;
sbMessage.action=操作;
sbMessage.config=config;
this.messageQueue.push(sbMessage);
如果(!this.isInstanceVisible){
this.showNext();
}
}
私人showNext(){
if(this.messageQueue.length==0){
返回;
}
const message=this.messageQueue.shift();
this.isInstanceVisible=true;
this.snackBarRef=this.snackBar.open(
留言,留言,
信息。行动,
message.config
);
此.snackBarRef.afterdismised().subscribe(()=>{
this.isInstanceVisible=false;
this.showNext();
});
}
}
消息列表:

messages = [
  {
    text: "This is message 1",
  },
  {
    text: "This is message 2",
  }
])

循环浏览它们并显示一条又一条消息

message.forEach( (message, index) => {

        setTimeout(() => {

            this.snackBar.open(message.text, action, {
                duration: this.timeOut,
                verticalPosition: 'bottom', // 'top' | 'bottom'
                horizontalPosition: 'end', //'start' | 'center' | 'end' | 'left' | 'right'
                panelClass: [className],
            });


        }, index * (this.timeOut+500)); // 500 - timeout between two messages

    });
演示:


面对另一个需求的相同问题,当所有
snackbar
关闭时,需要通知调用函数,我最终使用递归使用此解决方案:

调用方法:

testFunction(): void {
    this.showMsgs().subscribe(() => {
        // Do stuff after all messages were closed
    }
}
以及一个接一个地显示所有消息并让调用者运行所有消息已关闭的功能:

showMsgs(): Observable<any> {
    if (this.msgList.length) {
        const msg = this.msgList.pop();
        let closedEvent: Observable<any>;
        // If there are other msgs they should be shown first
        if (this.msgList.length) {
            closedEvent = this.showMsgs().pipe(
                switchMap(() => {
                    return this.snacBar.open(msg, 'Ok', {
                        verticalPosition: 'top' }).afterDismissed();
                }));
        } else { 
            // This is the only msg on the list, show it and return the close subscription
            closedEvent = this.snacBar.open(msg, 'Ok', {
                verticalPosition: 'top' }).afterDismissed();
        }
        return closedEvent;
    }
showMsgs():可观察{
如果(此.msgList.length){
const msg=this.msgList.pop();
让近距离观察:可观察;
//如果有其他MSG,则应首先显示它们
如果(此.msgList.length){
closedEvent=this.showMsgs().pipe(
开关映射(()=>{
返回此.snacBar.open(消息“Ok”{
verticalPosition:'top'}).AfterDiscomered();
}));
}否则{
//这是列表上唯一的消息,显示它并返回关闭订阅
closedEvent=this.snacBar.open(消息“Ok”{
verticalPosition:'top'}).AfterDiscomered();
}
回归近距离;
}
这是我的解决方案

从'@angular/core'导入{Injectable,NgZone,OnDestroy};
从“@angular/material/snakp bar”导入{matsnakbar,matsnakbaref,textonlysnakbar};
从'rxjs'导入{BehaviorSubject,EMPTY};
从“rxjs/operators”导入{concatMap};
接口ToasterMessage{
类型:ToasterMessageType;
消息:字符串;
}
@注射的({
providedIn:'根'
})
导出类SnackService实现OnDestroy{
私有的toastSteam:BehaviorSubject=新的BehaviorSubject({});
private toastStream$=this.toastStream.asObservable();
建造商(专用蛇栏:Matsnakbar,专用区域:NgZone){
//对于每一条toast消息,我们映射一个可观察的对象,并等待上一条消息
//完成。如果需要其他行为,我们可以使用mergeMap或switchMap
这个.toastStream$.pipe(
concatMap((toast:ToasterMessage |{})=>{
如果(!(‘键入’在吐司中)){
返回空;
}
返回此.handleToastMessage(toast).afterDiscomered();
})
).订阅(())=>{
});
}
openSnackBar(消息:string,
操作:字符串|未定义,
颜色:string='green snackbar'):matsnakbarref{
返回此.zone.run(()=>{
const snackBarRef=this.snackBar.open(消息、操作、{
持续时间:4000,
panelCl
testFunction(): void {
    this.showMsgs().subscribe(() => {
        // Do stuff after all messages were closed
    }
}
showMsgs(): Observable<any> {
    if (this.msgList.length) {
        const msg = this.msgList.pop();
        let closedEvent: Observable<any>;
        // If there are other msgs they should be shown first
        if (this.msgList.length) {
            closedEvent = this.showMsgs().pipe(
                switchMap(() => {
                    return this.snacBar.open(msg, 'Ok', {
                        verticalPosition: 'top' }).afterDismissed();
                }));
        } else { 
            // This is the only msg on the list, show it and return the close subscription
            closedEvent = this.snacBar.open(msg, 'Ok', {
                verticalPosition: 'top' }).afterDismissed();
        }
        return closedEvent;
    }