coffeescript

2 posts

AngularJS - Fix "Referencing DOM nodes in Angular expressions is disallowed"

When using AngularJS, sometimes you may see this error "Referencing DOM nodes in Angular expressions is disallowed". This may be caused by returning a jQuery expression in your scope functions.

For example, following code will have this issue.

angular.module('test', [])  
    .controller('thing', ['$scope', function ($scope) {
        $scope.action = function() {
            return $("#hello").text("World");
        };
    }]);

This is common when using CoffeeScript, because CoffeeScript adds a return statement by default.

For example, when using CoffeeScript, it's common to have code like this:

$scope.action = () ->
  $('#hello').text('world')

The code above will have this issue. A simple fix for this is:

$scope.action = () ->
  $('#hello').text('world')
  ''

CoffeeScript Notes and Tips

CoffeeScript is a popular language used by many frontend developers, I collected some useful notes and tips.

Find first/last element in array

CoffeeScript's destructuring assignment can be used to easily get array's first and last element.

[first, ..., last] = 'a,b,c'.split(',')
[first, ...] = 'a,b,c'.split(',')
[..., last] = 'a,b,c'.split(',')

Conditional(Tenary) operator

CoffeeScript has no conditional(tenary) operator ?:, use following instead:

valid = if length > 0 then true else false  

and it will be compiled to JavaScript like this:

var valid;

valid = length > 0 ? true : false;  

Loop with condition

Given an array, it's very easy to loop each element and process it, like below:

process(item) for item in items  

If you want to only process certain elements, you can use following code:

process(item) for item in items when isValid(item)  

Bind this using =>

Using CoffeeScript's fat arrow (=>), we don't need to use another
variable to capture this any more.

elem.addEventListener('onclick', () =>  
  @itemSelected()
false)  

Return value

In CoffeeScript, function always return its final value, so you don't need to use return explicitly in last statement.

myFunc = () ->  
  val = 'Hello'
  process(val)
  val

is the same as

myFunc = () ->  
  val = 'Hello'
  process(val)
  return val

Iterate object properties

To iterate objects in CoffeeScript, use for ... of, like below:

for key,value of hash  
  process(key, value)

If you want to iterate only object's own properties, use for own ... of, like below:

for own key,value of hash  
  process(key, value)

and it's compiled to following JavaScript code with hasOwnProperty check.

var key, value,  
  __hasProp = {}.hasOwnProperty;

for (key in hash) {  
  if (!__hasProp.call(hash, key)) continue;
  value = hash[key];
  process(key, value);
}