Как обработать асинхронное логическое значение в шаблоне - PullRequest
0 голосов
/ 17 октября 2019

Я пытаюсь реализовать простой обработчик исключений в моем угловом приложении, но у меня возникла проблема на последнем шаге, где я хочу показать сообщение для пользователя через диалоговое окно primeng. Для проверки исходов у меня есть конечная точка контроллера, где я просто выкидываю исключение. Это приводит к моему перехватчику http, затем к обработчику исключений, где я вызываю метод showError () моей службы уведомлений, который Subjects выдает displayModal true и строку сообщения. В модальном компоненте ошибки я подписываюсь на эти темы. Кажется, что после консольного выхода из приложения, проверка видимости не запускается после того, как я назначил true для переменной showDialog компонентов диалога, поэтому диалоговое окно становится видимым только после того, как на странице произойдет какое-то другое событие. Вот код.

Перехватчик:

@Injectable()
export class ServerErrorInterceptor implements HttpInterceptor {

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    return next.handle(request).pipe(
        // retry the HTTP call once
        retry(1),
      catchError((error: HttpErrorResponse) => {
        //check statuses if you want
        if (error.status === 418) {
            // do whatever you want
            } else {
              return throwError(error);
            }
        })
      );    
    }
}

ErrorHandler:

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {

    constructor(private injector: Injector) { }

    handleError(error: Error | HttpErrorResponse) {
        const errorService = this.injector.get(ErrorService);
        const logger = this.injector.get(LoggingService);
        const notifier = this.injector.get(NotificationService);

        let message;
        let stackTrace;

        if (error instanceof HttpErrorResponse) {
            message = errorService.getServerMessage(error);
            console.log(error.error.message);
            stackTrace = errorService.getServerStack(error);
            notifier.showError(message);
        } else {
            message = errorService.getClientMessage(error);
            stackTrace = errorService.getClientStack(error);
            notifier.showError(message);
        }

        logger.logError(message, stackTrace);

        console.error(error);
    }
}

NotificationService:

@Injectable({
    providedIn: 'root'
})
export class NotificationService {

    // TODO: implement a proper NotificationService!

    //displayModal: Subject<boolean> = new Subject();
    displayModal: Subject<boolean> = new Subject();
    message: Subject<string> = new Subject();

    constructor() { }

    showSuccess(message: string): void {
        alert(message);
    }

    public showError(message: string): void {
        this.message.next(message);
        this.displayModal.next(true);
    }
}

ErrorModalComponent:

@Component({
  selector: 'app-error-modal',
  templateUrl: './error-modal.component.html',
  styleUrls: ['./error-modal.component.css']
})
export class ErrorModalComponent implements OnInit {

    constructor(private notificationService: NotificationService) {}

    displayModalSubcription: Subscription;
    messageSub: Subscription;
    displayModal: boolean = false;
    message: string;

    ngOnInit() {
    this.messageSub = this.notificationService.message.subscribe(message => {
      this.message = message;
    });

    this.displayModalSubcription = this.notificationService.displayModal
        .subscribe(displayModal => {
          this.displayModal = displayModal;
    });
  }
}

Шаблон диалога:

<p-dialog [contentStyle]="{'overflow':'visible'}" modal="true" header="Error occured" [(visible)]="displayModal" >
    {{message}}
</p-dialog>

Если я пропустил http-вызов и просто привязал к кнопкеtificationService.showError (), он работает, поэтому я думаю, что он должен что-то делать сасинхронное поведение http-вызовов, но я не уверен, потому что тот факт, что у меня уже есть ошибка, означает, что у меня есть ответ на http-вызов ... Я совершенно новичок в angular, поэтому все еще есть некоторые туманные поля.

Любая помощь очень ценится!

Ответы [ 2 ]

0 голосов
/ 18 октября 2019

Это может быть обходной путь, но по крайней мере это работает. Я заставляю обнаружение изменений с помощью ChangeDetectorRef после установки displayModal и сообщения в true:

@Component({
  selector: 'app-error-modal',
  templateUrl: './error-modal.component.html',
  styleUrls: ['./error-modal.component.css']
})
export class ErrorModalComponent implements OnInit, OnDestroy {

  displayModalSubcription: Subscription;
  messageSub: Subscription;
  displayModal: boolean = false;
  message: string;

  constructor(private notificationService: NotificationService, private cdRef: ChangeDetectorRef) {}

  ngOnInit() {
    this.messageSub = this.notificationService.message.subscribe(message => {
      this.message = message;
      this.cdRef.detectChanges();
    });

    this.displayModalSubcription = this.notificationService.displayModal.subscribe(displayModal => {
      this.displayModal = displayModal;
      this.cdRef.detectChanges();
    });
  }

  ngOnDestroy() {
    this.displayModalSubcription.unsubscribe();
  }
}
0 голосов
/ 17 октября 2019

Ваша служба уведомлений помечена как private, и вы ссылаетесь на нее, по вашему мнению. Это должно привести к ошибке.

Этот ErrorModalComponent должен постоянно находиться в текущем виде (независимо от того, по какому маршруту вы находитесь).

Попробуйте это:

NotificationService:

@Injectable({
    providedIn: 'root'
})
export class NotificationService {

    // TODO: implement a proper NotificationService!

    displayModal = new BehaviorSubject<boolean>(false);
    message = new BehaviorSubject<string>();

    constructor() { }

    showSuccess(message: string): void {
        alert(message);
    }

    public showError(message: string): void {
        this.message.next(message);
        this.displayModal.next(true);
    }

    public hideError(): void {
        this.displayModal.next(false);
    }
}

ErrorModalComponent:

@Component({
  selector: 'app-error-modal',
  templateUrl: './error-modal.component.html',
  styleUrls: ['./error-modal.component.css']
})
export class ErrorModalComponent implements OnInit {

    showModal: boolean;
    message: string;

    constructor(private notificationService: NotificationService) {}

    ngOnInit() {
        this.notificationService.displayModal.subscribe(v => this.showModal = v);
        this.notificationService.message.subscribe(m => this.message = m);
    }
}

Представление:

<p-dialog [contentStyle]="{'overflow':'visible'}" 
    modal="true" 
    header="Error occured" 
    [(visible)]="showModal" >
    {{message}}
</p-dialog>

Модалу необходимо что-то, чтобы закрыть его. Свяжите эту кнопку с локальной функцией closeModal в вашем компоненте и оттуда вызовите функцию hideModal notificationService.

Надеюсь, это поможет.

...