Я создал собственный компонент Toast, который вызывается при каждой ошибке запроса службой уведомлений (вызывается перехватчиком http). Вот как выглядит мой пользовательский компонент toast:
toast.component. html
<div class="wrapper mx-auto shadow-max" *ngIf="toasts.length">
<div [@toast] *ngFor="let toast of toasts" class="mw-100" [ngClass]="getToastClass(toast)" role="alert">
<div class="toast-header">
{{ 'notify.header.' + getToastType(toast) | translate }}
<button
type="button"
class="close"
data-dismiss="alert"
aria-label="Close"
(click)="removeToast(toast)"
>
<i class="icon" aria-hidden="true">close</i>
</button>
</div>
<div class="toast-body">
<p>{{ 'notify.body.' + toast.message | translate }}</p>
<p>{{ toast.detailsMessage }}</p>
</div>
</div>
</div>
toast.component.ts
import { animate, style, transition, trigger } from '@angular/animations';
import { Component, Input, OnInit } from '@angular/core';
import { ToastType } from '../../enums/toast-type.enum';
import { Toast } from '../../model/toast.model';
import { Utils } from '../../utils/utils';
import { ToasterService } from './toaster.service';
@Component({
selector: 'bigdata-toaster',
moduleId: module.id,
templateUrl: './toast.component.html',
//styleUrls: ['./toast.component.scss'],
animations: [
trigger('toast', [
transition('void => *', [style({ transform: 'scale3d(.3, .3, .3)' }), animate(200)]),
transition('* => void', [animate(200, style({ transform: 'scale3d(.0, .0, .0)' }))])
])
]
})
export class ToastComponent implements OnInit {
@Input() id: string;
toasts: Toast[] = [];
constructor(private readonly toastService: ToasterService) {}
ngOnInit() {
this.toastService.getToast(this.id).subscribe((toast: Toast) => {
if (!toast.message) {
// clear alerts when an empty alert is received
this.toasts = [];
return;
}
// add alert to array
this.toasts.push(toast);
setTimeout(() => this.removeToast(toast), 5000);
});
}
removeToast(toast: Toast) {
this.toasts = this.toasts.filter(x => x !== toast);
}
getToastType(toast: Toast) {
return Utils.enumToString(ToastType, toast.type).toLocaleLowerCase();
}
getToastClass(toast: Toast) {
if (!toast) {
return;
}
switch (toast.type) {
case ToastType.Success:
return 'toast toast-success fade show';
case ToastType.Error:
return 'toast toast-danger fade show';
case ToastType.Info:
return 'toast toast-info fade show';
case ToastType.Warning:
return 'toast toast-warning fade show';
}
}
}
toaster.service. ts
import { Injectable } from '@angular/core';
import { NavigationStart, Router } from '@angular/router';
import { Observable, Subject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { ToastType } from '../../enums/toast-type.enum';
import { Toast } from '../../model/toast.model';
@Injectable({
providedIn: 'root'
})
export class ToasterService {
private readonly subject = new Subject<Toast>();
private keepAfterRouteChange = false;
constructor(private readonly router: Router) {
// clear alert messages on route change unless 'keepAfterRouteChange' flag is true
this.router.events.subscribe(event => {
if (event instanceof NavigationStart) {
if (this.keepAfterRouteChange) {
// only keep for a single route change
this.keepAfterRouteChange = false;
} else {
this.clear();
}
}
});
}
getToast(toastId?: string): Observable<any> {
return this.subject.asObservable().pipe(filter((x: Toast) => x && x.toastId === toastId));
}
success(message: string, detailsMessage?: string) {
this.toast(new Toast({ message, type: ToastType.Success, detailsMessage }));
}
error(message: string, detailsMessage?: string) {
this.toast(new Toast({ message, type: ToastType.Error, detailsMessage }));
}
info(message: string, detailsMessage?: string) {
this.toast(new Toast({ message, type: ToastType.Info, detailsMessage }));
}
warn(message: string, detailsMessage?: string) {
this.toast(new Toast({ message, type: ToastType.Warning, detailsMessage }));
}
toast(toast: Toast) {
this.keepAfterRouteChange = toast.keepAfterRouteChange;
this.subject.next(toast);
}
clear(toastId?: string) {
this.subject.next(new Toast({ toastId }));
}
}
Мой сервис уведомлений выглядит следующим образом:
import {HttpErrorResponse} from '@angular/common/http';
import { Injectable } from '@angular/core';
// import { ActiveToast, IndividualConfig, ToastrService } from 'ngx-toastr';
import { ActiveToast, IndividualConfig } from 'ngx-toastr';
import {ToastComponent} from '../../components/toast/toast.component';
import {ToasterService} from '../../components/toaster/toaster.service';
/**
* Toaster Notification Component
*/
@Injectable()
export class NotificationService {
private readonly DEFAULT_TOASTR_SETTINGS: Partial<IndividualConfig> = {
closeButton: true,
positionClass: 'toast-top-right',
toastComponent: ToastComponent, // custom toast
toastClass: 'toast',
progressBar: true,
tapToDismiss: false,
disableTimeOut: true,
enableHtml: true
};
constructor(private toastrService: ToasterService) {
}
showErrorNotification(err: HttpErrorResponse) {
this.toastrService.success('approve_success');
}
}
Я объявил свой сервис уведомлений в своем app.module.ts:
providers: [
NotificationService,
{
provide: HTTP_INTERCEPTORS, useClass: AppHttpInterceptor, multi: true
}
]
И мой Перехватчик HTTP:
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {ToastrService} from 'ngx-toastr';
import {Observable, of} from 'rxjs';
import {catchError} from 'rxjs/operators';
import {NotificationService} from './shared/services/notifications/notifications.service';
@Injectable()
export class AppHttpInterceptor implements HttpInterceptor {
// constructor(public toastr: ToastrService) {
// }
constructor(public notif: NotificationService) {
}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError((err: any) => {
if (err instanceof HttpErrorResponse) {
// this.notif.showNotification(MESSAGE_TYPE.Error, err.message, err.status.toString(), {disableTimeOut: true});
this.notif.showErrorNotification(err);
}
return of(err);
}));
}
}
Мой перехватчик HTTP работает, я могу что-то зарегистрировать. Но у меня ничего нет в моем интерфейсе. Что-нибудь в консоли тоже. Меня сильно вдохновил другой код, поэтому я думаю, что что-то не так.
Пожалуйста, что я здесь не так делаю? Спасибо.