Reputation: 161
I have a SystemMessageService
which creates instances of SystemMessageComponent
using the following method
createSystemMessage(message: string, vcr: ViewContainerRef, time: number = 4500, isErrorMessage: boolean = false, isWarningMessage: boolean = false, isSuccessMessage: boolean = false){
let systemMessageCmpFactory = this.componentFactoryResolver.resolveComponentFactory(SystemMessageComponent);
this.hostViewContainerRef = vcr;
this.hostViewContainerRef.clear();
this.systemMessageCmpRef = this.hostViewContainerRef.createComponent(systemMessageCmpFactory);
this.systemMessageCmpRef.instance.message = message;
this.systemMessageCmpRef.instance.timeUntilDestruction = time;
this.systemMessageCmpRef.instance.isErrorMessage = isErrorMessage;
this.systemMessageCmpRef.instance.isWarningMessage = isWarningMessage;
this.systemMessageCmpRef.instance.isSuccessMessage = isSuccessMessage;
this.closeSubMsg = this.systemMessageCmpRef.instance.closeMessage.subscribe(() => {
this.closeSubMsg.unsubscribe();
this.hostViewContainerRef.clear()
})
}
Now I have a notifier in SystemMessageService
,
private systemMessageNotifier$: Subject<string> = new Subject();
public systemMessageObs$ = this.systemMessageNotifier$.asObservable();
emitSystemMessage(systemMessage: string){
this.systemMessageNotifier$.next(systemMessage);
}
which informs app.component.ts
when to display a new system message
@ViewChild('systemMessageHost', {read: ViewContainerRef}) systemMessageHost: ViewContainerRef;
constructor(private systemMessageService: SystemMessagesService){
}
ngOnInit(): void {
this.systemMessageService.systemMessageObs$.subscribe(systemMessage => {
this.systemMessageService.createSystemMessage(systemMessage, this.systemMessageHost, 60*1000*60)
})
}
but the problem is that messages would overlap if sent sequentially, for example if I call the following in any component
this.systemMessageService.emitSystemMessage("Message1");
this.systemMessageService.emitSystemMessage("Message2");
I would only show "Message2" but I want to show "Message1" first and if the user closes the component, then "Message2" should be shown afterwards. How would I implement this? The SystemMessageComponent
can be closed either by timeout or click on a close button.
Upvotes: 0
Views: 474
Reputation: 161
I solved it this way: I use a variable to check whether an instance exists. If it exists I push the next message in an array. When the instance is destroyed, I use a notifier to inform app.component
that the instance was destroyed so that, if there is another message, the next message can be shown.
private systemMessageNotifier$: Subject<SystemMessage> = new Subject();
public systemMessageObs$ = this.systemMessageNotifier$.asObservable();
private sysMsgDestroyedNotifier$: Subject<any> = new Subject();
public systemMessageDestroyed$ = this.sysMsgDestroyedNotifier$.asObservable();
createSystemMessage(message: string, vcr: ViewContainerRef, messageType: SystemMessageType, noTimeOut: boolean = false, timeUntilDestruction: number = 1000*3600){
let systemMessageCmpFactory = this.componentFactoryResolver.resolveComponentFactory(SystemMessageComponent);
this.hostViewContainerRef = vcr;
this.hostViewContainerRef.clear();
this.systemMessageCmpRef = this.hostViewContainerRef.createComponent(systemMessageCmpFactory);
this.systemMessageCmpRef.instance.message = message;
this.systemMessageCmpRef.instance.timeUntilDestruction = timeUntilDestruction;
this.systemMessageCmpRef.instance.messageType = messageType;
this.systemMessageCmpRef.instance.noTimeOut = noTimeOut;
this.closeSubMsg = this.systemMessageCmpRef.instance.closeMessage.subscribe(() => {
this.closeSubMsg.unsubscribe();
this.hostViewContainerRef.clear();
this.sysMsgDestroyedNotifier$.next();
})
}
export class AppComponent implements OnInit {
delayedSystemMessages = [];
isSystemMessageComponentActive: boolean = false;
@ViewChild('systemMessageHost', {read: ViewContainerRef}) systemMessageHost: ViewContainerRef;
constructor(private systemMessageService: SystemMessagesService){
}
ngOnInit(): void {
this.systemMessageService.systemMessageDestroyed$.subscribe(() => {
if(this.delayedSystemMessages.length > 0){
this.isSystemMessageComponentActive = false;
let message = this.delayedSystemMessages.shift()
this.systemMessageService.emitSystemMessage(message);
}
})
this.systemMessageService.systemMessageObs$.subscribe(systemMessage => {
if(this.isSystemMessageComponentActive){
this.delayedSystemMessages.push(systemMessage)
return;
}
this.isSystemMessageComponentActive = true;
this.systemMessageService.createSystemMessage(systemMessage.message, this.systemMessageHost, systemMessage.messageType, systemMessage.noTimeOut, systemMessage.timeUntilDestruction)
})
}
}
Upvotes: 0