Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I debug/dump a value from an ng-bind {{ }} Angular expression?

Tags:

angularjs

Is there a good way to dump or inspect the results of an expression? Sometimes when I do

{{some_expression}}

, nothing shows up on the page where the result of that expression should show up. How do I determine if the expression returned a null, an undefined, or an empty string ''?

If it's a normal object, like this, it will show a nice programmer-friendly representation of the object, which is great:

{{ {'a': 1} }}

But if you try to inspect an expression that evaluates to null, undefined, or '', they are all indistinguishable from each other!

{{null}}
{{undefined}}
{{''}}

So how can you tell which one it was??

I tried using JSON.stringify:

{{ JSON.stringify(null) }}

but JSON seems to be unavailable from an Angular expression because it's a method from window and not a property of the scope (see related question about accessing methods from window).

I tried using typeof:

typeof {}: {{ typeof {'a': 1} }}

but it results in an error:

Error: [$parse:syntax] Syntax Error: Token '{' is an unexpected token at column 9 of the expression [ typeof {'a': 1} ] starting at [{'a': 1} ].

So how can I get it to dump the value into the template using something like JSON.stringify (… or console.log)?


Generally speaking, is there a good way to debug Angular expressions other than trial and error? Since Angular expressions are so "forgiving", they don't seem to raise errors; they just silently swallow the errors and return undefined:

In JavaScript, trying to evaluate undefined properties generates ReferenceError or TypeError. In Angular, expression evaluation is forgiving to undefined and null.

But without seeing some kind of error message, how do you know what part of the expression Angular had trouble with?

like image 730
Tyler Rick Avatar asked Apr 04 '14 15:04

Tyler Rick


People also ask

How to use ng bind in AngularJS?

The ng-bind directive tells AngularJS to replace the content of an HTML element with the value of a given variable, or expression. If the value of the given variable, or expression, changes, the content of the specified HTML element will be changed as well.

What is Ng bind HTML?

The ng-bind-html directive is a secure way of binding content to an HTML element.

Which of the following is a valid AngularJS expression?

AngularJS expressions are JavaScript-like code snippets that are mainly placed in interpolation bindings such as <span title="{{ attrBinding }}">{{ textBinding }}</span> , but also used directly in directive attributes such as ng-click="functionExpression()" . For example, these are valid expressions in AngularJS: 1+2.


4 Answers

You can add a custom filter for debugging purposes:

app.filter('debug', function() {
  return function(input) {
    if (input === '') return 'empty string';
    return input ? input : ('' + input);
  };
});

Usage:

{{ value | debug }}

Demo: http://plnkr.co/edit/U44BCjBhgsFedRkHASlc?p=preview

like image 92
tasseKATT Avatar answered Oct 17 '22 17:10

tasseKATT


The recommended way is to use AngularJS's logging service $log. First you need to inject the service into your controller and assign it to a scope variable like so:

app.controller('MyCntrl', function($log){
    $scope.$log = $log;

Then in your template, us it like ay other function:

<span>{{$log.log(value}}</span>

If you want to be able to use typeof, it works basically the same way:

$scope.getTypeOf = function(val){ return typeof val; };

<span>{{getTypeOf(val)}}</span>
like image 32
km6zla Avatar answered Oct 17 '22 15:10

km6zla


The built-in JsonPipe might be easier...

{{ object | json }}

See: https://angular.io/api/common/JsonPipe

like image 39
Daniel Sauvé Avatar answered Oct 17 '22 15:10

Daniel Sauvé


Based on tasseKATT's and ogc-nick's great answers, I added these two filters. They're written in CoffeeScript but here's the JavaScript equivalent if you prefer. Posting here in case it's helpful to anyone else...

.filter 'debug', ->
  (input) ->
    if typeof input is 'undefined'
      'undefined'
    else
      JSON.stringify(input)

.filter 'typeof', ->
  (input) ->
    typeof input

Now I can get some meaningful debugging output from each of the following expressions:

  {{null | debug}}
  {{undefined | debug}}
  {{'' | debug}}
like image 41
Tyler Rick Avatar answered Oct 17 '22 15:10

Tyler Rick