7

Here's a fiddle for illustration. When there's an ng-click directive that (for example) calls a function not defined on the controller's $scope (or its parents), it fails silently. When I'm trying to debug a webpage, this behavior is maddening, as a mis-typed function name can mean a lot of wasted time hunting it down. How can I find out when errors are being swallowed like this, and why is the answer "you can't?"


HTML

<div ng-app="AngularApp">
    <div ng-controller="FooController">
        <button ng-click="noError()"> noError() </button>
        <button ng-click="error()"> error() </button>
        <button ng-click="works()"> works() </button>
        <br/>
        <p ng-bind="foo"></p>
    </div>
</div>

Javascript

var angularApp = angular.module('AngularApp', []);

angularApp.controller('FooController', ['$scope', function($scope) {
    $scope.foo = 0;
    
    $scope.works = function () {
        $scope.foo += 1; // no error, everything works
    };
    
    $scope.error = function () {
        $scope.foo += baz; // ReferenceError: baz is not defined
    };
        
    // noError is not defined in the controller, so errors suddenly don't matter?
}]);

1 Answer 1

9

Why ngClick doesn't throw Reference errors on bad references

ngClick defaults to using $parse under the covers. You can see that in the source here.

$parse is an angular helper function that parses angular expressions.

You can read about the rules for expressions in the documentation but the relevant snippet is below.

Angular Expressions vs. JavaScript Expressions Angular expressions are like JavaScript expressions with the following differences:

  • Context: JavaScript expressions are evaluated against the global window. In Angular, expressions are evaluated against a scope object.
  • Forgiving: In JavaScript, trying to evaluate undefined properties generates ReferenceError or TypeError. In Angular, expression evaluation is forgiving to undefined and null.
  • No Control Flow Statements: you cannot use the following in an Angular expression: conditionals, loops, or exceptions.
  • Filters: You can use filters within expressions to format data before displaying it.

How can you work around this?

The documentation then anticipates your objections and responds to them with

If you want to run more complex JavaScript code, you should make it a controller method and call the method from your view. If you want to eval() an Angular expression yourself, use the $eval() method.

So basically the idea is that expressions are for simple code, and any complex logic should be run from with a controller. In your case, you're not really doing complex things, just making bad references, but it seems like the answer to that from Angular's point of view is simply "be more disciplined" and structure your code to ensure your references will at least exist.

Why does it do it this way?

This has already been mostly covered, but in essence, expressions are meant to handle very simple logic, and are optimized for simplicity and not breaking your app. The idea is that anything that requires more extensive error checking can be handled in code.

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

4 Comments

I understand the separation of concerns as far as where logic belongs; I am very fond of how complex js is not allowed in angular expressions. It makes me sad, though, that "be more disciplined" seems to equate to "never make typos."
I think try {} catch{} could help. But reality, some issue about typos should never happen. My opinion.
No one is going to wrap every piece of "very simple logic" in the view in a try/catch. Too much clutter. My problem is that very simple logic can still have errors, and because angularjs is forgiving, they go unnoticed.
Check for typos first before spending hours searching for a bug.

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.