Bernard Ng
Bernard Ng

Reputation: 111

Angular 2 doesn't update view after exception is thrown

When an exception is caught by Angular 2's exception handler, the UI no longer 'updates'.

I have a very simple example here:

import { Component, ExceptionHandler, Injectable, OnInit, provide } from '@angular/core';
import { bootstrap } from '@angular/platform-browser-dynamic';
import { Subject } from 'rxjs/Subject'

export interface Alert {
  message: string;
}

@Component({
  selector: 'my-app',
  template : `
  <h3>Parent</h3>
  {{aValue}}
  <br/>
  <br/>
  <button (click)='doIt()'>do it</button>
  <br/>
  <br/>
  <button (click)='breakIt()'>break it</button>
  `
})

export class App implements OnInit {
  private aValue: boolean = true
  constructor() { }
  
  alerts: Alert[] = [];
  
  doIt(){
    console.log('Doing It')
    this.aValue = !this.aValue
  }
  
  breakIt(){
    console.log('Breaking It')
    throw new Error('some error')
  }
}

bootstrap(App).catch(err => console.error(err));

The Do It button flips the boolean which is reflected in the interpolated value in the template. However, once the Break It button is pressed (which cases an error to be thrown), the interpolated value no longer updates when the 'Do it' button is hit. However, the console still logs the messages Doing it.

The problem I'm dealing with is I would like to create a custom exception handler that warns the user and possibly does some work to clear a form when something has gone wrong, but what I'm seeing is if I throw an error on a button click to test it, all UI updates stop. However, buttons continue to function, meaning any buttons that post requests will do so if the form is in a good state. The UI however has ceased to update and inform the user what is happening.

I'm not sure if this is a problem with Zones or something else, but attempting an NgZone.run() didn't seem to solve the problem for me. If an error is meant to break a component's UI, what's the correct approach to my problem?

Upvotes: 11

Views: 3667

Answers (2)

yurzui
yurzui

Reputation: 214195

Since angular 4.1.1 (2017-05-04) https://github.com/angular/angular/commit/07cef36

fix(core): don’t stop change detection because of errors

  • prevents unsubscribing from the zone on error
  • prevents unsubscribing from directive EventEmitters on error
  • prevents detaching views in dev mode if there on error
  • ensures that ngOnInit is only called 1x (also in prod mode)

it should work without additional code

@Component({
  selector: 'my-app',
  template : `
    {{aValue}}
    <button (click)='doIt()'>do it</button>
    <button (click)='breakIt()'>break it</button>
  `
})

export class App implements OnInit {
  private aValue: boolean = true

  doIt(){
    console.log('Doing It')
    this.aValue = !this.aValue
  }

  breakIt(){
    console.log('Breaking It')
    throw new Error('some error')
  }
}

Plunker Example

Upvotes: 5

Andrei Zhytkevich
Andrei Zhytkevich

Reputation: 8099

Don't rely on code execution after an unhandled Exception happened. You have to handle the exception in the place where you expect it to happen.

Error handling: http://www.javascriptkit.com/javatutors/trycatch.shtml

Upvotes: 1

Related Questions