4

I have an app with both Angular (2+) and AngularJS (1.x). We are using a third party AngularJS library that reads an object from its attrs array in a link function, like so:

//3rd party lib code:
module.directive('test', () => ({
  template: `Look at the console`,
  link(elt, scope, attrs) {
    console.log('link attrs.props', attrs.props);
  }
})) 

Template:

<!-- someObject = {name: 'foo'} -->
<test props="{{someObject}}"></test>

We just upgraded to the latest version of AngularJS and we noticed a problem. Normally, attrs.props evaluates to a string representation of the object. Instead of getting a stringified object, we're getting "[object Object]"

I attempted a minimal reproduction but I couldn't reproduce the problem, until I tried importing Zone.js as you can see on this stackblitz: https://stackblitz.com/edit/angularjs-attrs-test?file=app.js

If Zone.js is imported (which we need for Angular 2+), then attrs.props is "[object Object]". Without it, attrs.props is {name: 'foo'}.

Is this a known issue? Is there a workaround?

georgeawg
  • 48,608
  • 13
  • 72
  • 95
Ryan Silva
  • 925
  • 2
  • 9
  • 17

2 Answers2

3

It is a good practice to always load ZoneJS before anything else, otherwise some strange problems like that can happen. In you example, if you simple move the ZoneJS import to the first line, it solves the problem.

William Grasel
  • 1,181
  • 1
  • 10
  • 11
2

ZoneJS overrides Object.prototype.toString method which leads to unexpected behavior in AngularJS stringify function:

function stringify(value) {
  if (value == null) { // null || undefined
    return '';
  }
  switch (typeof value) {
    case 'string':
      break;
    case 'number':
      value = '' + value;
      break;
    default:
      if (hasCustomToString(value) && !isArray(value) && !isDate(value)) {
                     \/
                    true
        value = value.toString(); // will be called since zone js overrided this method
      } else {
        value = toJson(value); // will be called without zonejs
      }
  }

  return value;
}

In order to work around it you can disable this patch:

window.__Zone_disable_toString = false; 
import 'zone.js/dist/zone';

Forked Stackblitz

yurzui
  • 205,937
  • 32
  • 433
  • 399