javascript Angular 2/4 - Material Design Snackbars 按顺序显示多个消息
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47409869/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 2/4 - Material Design Snackbars multiple message in sequence
提问by ar099968
I have implemented a "snackbar service" that display a snackbar:
我已经实现了一个显示小吃店的“小吃店服务” :
snackbar.service.ts
小吃店.service.ts
import { Subscription } from 'rxjs/Subscription';
import { Subject } from 'rxjs/Subject';
import { Inject, Injectable, OnDestroy } from '@angular/core';
import { MatSnackBar, MdSnackBarConfig } from '@angular/material/snack-bar';
import { MdSnackBarRef, SimpleSnackBar } from '@angular/material/snack-bar';
export class SnackBarMessage {
message: string;
action: string = null;
config: MdSnackBarConfig = null;
}
@Injectable()
export class SnackBarService implements OnDestroy
{
private messageQueue: Subject<SnackBarMessage> = new Subject<SnackBarMessage>();
private subscription: Subscription;
private snackBarRef: MdSnackBarRef<SimpleSnackBar>;
constructor(public snackBar: MatSnackBar){
this.subscription = this.messageQueue.subscribe(message => {
this.snackBarRef = this.snackBar.open(message.message, message.action, message.config);
});
}
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.
*/
add(message: 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;
this.messageQueue.next(sbMessage);
}
}
I want display multiple snackbars in sequence:
我想按顺序显示多个小吃店:
test.component.ts
test.component.ts
import { Component } from '@angular/core';
import { SnackBarService } from 'app/core/services/snackbar.service';
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent {
constructor(public snackBarService: SnackBarService) {
this.snackBarService.add('A');
this.snackBarService.add('B');
this.snackBarService.add('C');
}
}
But all message are displayed at same time (overlapping).
但所有消息同时显示(重叠)。
How can I wait for a snackBar afterDismissedfor display a new message into messageQueue?
我怎样才能等待snackBar afterDismissed以将新消息显示到messageQueue 中?
采纳答案by Ankit
As @Aamir Khan pointed out - using afterDismissed, I have tweaked your code a bit.
正如@Aamir Khan 指出的那样-使用afterDismissed,我对您的代码进行了一些调整。
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();
});
}
And inside add()added this -
并在里面add()添加了这个 -
this.msgQueue.push(sbMessage);
if (!this.isInstanceVisible) {
this.showNext();
}
Caution- Its kind of a dirty and non standard way, not an ideal user experience (IMO), above code might have some memory leaks and race conditions, due to usage of flags.
注意-这是一种肮脏和非标准的方式,不是理想的用户体验 (IMO),由于使用了标志,上面的代码可能存在一些内存泄漏和竞争条件。
回答by MaylorTaylor
Here is @Ankit's Plunker broken out here.
这是@Ankit 的 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();
});
}
}
回答by Vivek Doshi
You can achieve this by making these simple changes :
您可以通过进行这些简单的更改来实现这一点:
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);
})
}
回答by Shailesh Ladumor
you need to use time out method. hide snackbar in specific time and open another snackbar using timeout function
您需要使用超时方法。在特定时间隐藏小吃店并使用超时功能打开另一个小吃店
constructor(public snackBarService: SnackBarService) {
this.snackBarService.add('A')
setTimeout(this.snackBarService.add('B'),10000);
setTimeout(this.snackBarService.add('C'),20000);
}
回答by Igor Simic
list of messages:
消息列表:
messages = [
{
text: "This is message 1",
},
{
text: "This is message 2",
}
];
];
loop through them and display one message after another
遍历它们并显示一条又一条消息
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
});
demo:
演示:
https://www.coditty.com/code/angular-material-display-multiple-snackbars-messages-in-sequence
https://www.coditty.com/code/angular-material-display-multiple-snackbars-messages-in-sequence

