17

While working inside Angular (Angular 4, 5), if a component raises Error (TypeError or null or undefined error or so), whole application breaks onward.

How can we deal with this, to catch errors on component level and possibly show a fallback UI, like React16 does using Error Boundaries.

4
  • Currently there is support to override the global implementation of the ErrorHandler. You could try to instantiate a provider object that overrides the default implementation at component level using the providers property of the Component decorator. Commented Jan 22, 2018 at 11:45
  • I am already overriding global ErrorHandler. If it can be provided at component level, it'd be great. Are you sure it's possible? Commented Jan 22, 2018 at 11:47
  • Probably too broad for what you'd like to have, but overriding the ExceptionHandler by your own is a possibility. See this article for more detailed usage. Commented Jan 22, 2018 at 11:49
  • Doesnt seem to be possible atm plnkr.co/edit/oZPbmFoqURuQQLqvpjKw?p=info Commented Jan 22, 2018 at 13:55

2 Answers 2

1

I would approach it by handling the error at Component level and have a service that listens to any errors happening at Component or Service level. Ex:

  1. Throw the error from the service
  2. catch the error in component
  3. Handle the error, process it and send the Error event with details to ErrorService.
  4. You can have a app level component "errorBannerComponent" which takes input from ErrorService and paint your UI.
  5. As soon as the error is received in ErrorService, The errorBannerComponent should display the error on screen.

Hope it helps.

Also By default, Angular comes with its own ErrorHandler that intercepts all the Errors that happen in our app and logs them to the console, preventing the app from crashing. We can modify this default behavior by creating a new class that implements the ErrorHandler:

You can find more details and example here:

Sign up to request clarification or add additional context in comments.

5 Comments

If say ngAfterContentChecked life cycle method raises undefined error, how can it be catched inside component or service.
there must be something unexpected going on in your code there. You should inspect your code. These lifeCycle hooks are comparatively safe to use compared to other functions.
You can share your code at stackblitz and i can take a look.
React's Error Boundaries ensure that if there's an unprecedented error at run time, it won't crash the application, also user will see a fall back UI. Run time errors, that aren't evident at compile/develop time, will crash Angular application. I was looking to solve this problem.
By default, Angular comes with its own ErrorHandler that intercepts all the Errors that happen in our app and logs them to the console, preventing the app from crashing. This can be modified by creating a new class that implements the ErrorHandler: You can read more here: medium.com/@aleixsuau/error-handling-angular-859d529fa53a
1

As the proposed solutions are rather dull. I tried to recreate it myself. The easiest solution would be to provide a module scoped custom ErrorHandler class. Thanks to this, you could even create a multiple different ErrorBoundaries.

My proposed solution can be seen here: https://stackblitz.com/edit/angular-ivy-brb143?file=src/app/widget/widget.module.ts

What is really important for this solution to work (atleast it didn't work otherwise for me). Was to provide the custom error handler as a part of a module rather than a component directly.

The important bits from the solutions:

module:

/**
 * This is really imporant as this allows us to provide a module scoped ErrorHandler
 */
@NgModule({
  imports: [CommonModule],
  declarations: [WidgetComponent],
  providers: [{ provide: ErrorHandler, useClass: WidgetErrorHandler }],
  exports: [WidgetComponent],
})
export class WidgetModule {}

component where we can throw, and catch error

@Component({
  selector: 'app-widget',
  templateUrl: './widget.component.html',
  styleUrls: ['./widget.component.css'],
})
export class WidgetComponent implements OnInit {
  constructor(@Inject(ErrorHandler) public widgetError: WidgetErrorHandler) {}

  ngOnInit() {
    this.widgetError.isError$.subscribe((error) =>
      console.log('component can act on error: ', error)
    );
  }

  public handleThrowErrorClick(): void {
    throw Error('Button clicked');
  }
}

and the handler iself


@Injectable()
export class WidgetErrorHandler implements ErrorHandler {
  public isError$: Subject<Error | any> = new Subject();

  handleError(error) {
    console.log('Intercepted error', error);
    this.isError$.next(error);
  }
}

1 Comment

This is great and neat @karoluS. I was suspicious if it would catch template originated runtime errors (renderer level errors), I tested and it did catch. My test is here. I'll also do a few more tests.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.