Reputation: 21855
I'm building a global error handler so it shows a bootstrap modal dialog showing details about the error. I have the following setup:
The error modal component defines a method called open()
, its template includes a button (to debug it) that calls the open()
and everything works fine, the modal is correctly shown with the binded text.
ErrorModalComponent code:
import { Component, ViewChild, TemplateRef } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { GlobalErrorHandler } from './global-error-handler.service';
@Component({
selector: 'app-error-modal',
templateUrl: './error-modal.component.html',
styles: []
})
export class ErrorModalComponent {
private _message: string;
@ViewChild('content') _modalTemplate: TemplateRef<any>;
constructor(private _modalService: NgbModal, private _globalErrorHandler: GlobalErrorHandler) {
this._globalErrorHandler.errorEventSource$.subscribe(errorMessage => {
this._message = errorMessage.toString();
this.open();
});
}
open() {
this._modalService.open(this._modalTemplate);
this._message = "A change test";
}
public get message(): string {
return this._message;
}
}
ErrorModalComponent html:
<button class="btn btn-info" (click)="open()">Show Modal</button>
<ng-template #content let-c="close" let-d="dismiss">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">It's not you, it's me: unhandled error</h4>
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')" data-dismiss="modal">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>We are sorry but something has slipped by and we have an uncontrolled error.</p>
<p>A notification has been sent to us and we will process it soon.</p>
<p>{{message}}</p>
</div>
<div class="modal-footer">
<div class="col-4">
<button type="button" class="btn btn-danger btn-block" (click)="c('Close click')" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</ng-template>
GlobalErrorHandler code:
import { ErrorHandler, Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
private errorEventSource = new Subject<string>();
errorEventSource$ = this.errorEventSource.asObservable();
handleError(error: any) {
this.errorEventSource.next(error);
}
}
When I put an exception somewhere in the code the event is captured, the open method called but the modal is not correctly shown and the binded text does not appear. It appears at the bottom of the page and it is disabled and you cannot click anywhere.
I don't get why this difference when calling the same method from two different places. Any hint?
This is the modal after clicking the button:
And this is the modal after raising an exception:
Upvotes: 2
Views: 875
Reputation: 65
I had the exact same problem but with a slightly different setup. I had a globalErrorHandler with a "handleError" function. apparently that function executes outside of the angular zone.
I fixed this by running the ngbMdal in zone.runguarded.
this.zone.runGuarded(() => {
this.modalService = this.injector.get(NgbModal);
const modalRef = this.modalService.open(ErrorComponent);
modalRef.componentInstance.errorMessage = error.message;
modalRef.componentInstance.stack = error.stack;
});
Don't forget the injection in the constructor
private zone: NgZone
Upvotes: 1