AngularJS: пользовательский компонент не будет отображаться (тост) - PullRequest
1 голос
/ 21 января 2020

Я создал собственный компонент 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 работает, я могу что-то зарегистрировать. Но у меня ничего нет в моем интерфейсе. Что-нибудь в консоли тоже. Меня сильно вдохновил другой код, поэтому я думаю, что что-то не так.

Пожалуйста, что я здесь не так делаю? Спасибо.

...