1

I have been Googling a lot to find answer for this but I wasn't able to do so. I found this issue, and I don't know what causes it. I know that workarounds exist, but I would like to know why this is happening.

Why am I not able to display prototypical objects in view from {{object}} expression?

By inspecting $scope i know that values are there, but i am not able to display them in JSON format on view.

Here is live example I made that tells everything.

http://plnkr.co/edit/Sm3LXLxbwQ7I5vo2fjbN?p=preview

Thanks in advance!

UPDATE: Live example updated, because previous link was broken!

2nd UPDATE:

Answers about Angular function witch ignores object properties with names starting with $ are completely right and i understand those, but yesterday i ran into same problem with Geolocation. Geolocation is not an Angular object, and it doesn't contain $ sign, but it also doesn't work. Please check new updated plnkr! And Thanks for effort

2 Answers2

0

Check this working demo: Plunker.

Your code doesn't show anything, because the filter doesn't show any properties starting with $. From AngularJS 1.4.3 source code Line 1176:

function toJsonReplacer(key, value) {
  var val = value;

  if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
    val = undefined;
  } else if (isWindow(value)) {
    val = '$WINDOW';
  } else if (value &&  document === value) {
    val = '$DOCUMENT';
  } else if (isScope(value)) {
    val = '$SCOPE';
  }

  return val;
}

So, if you assign some property to $location, say $location.myData = 'Joy';, this piece of data is shown correctly.

Well, if you assign the scope $scope.myScope = $scope; and show it {{ myScope | json }}, you will get plain string $SCOPE.

Joy
  • 9,430
  • 11
  • 44
  • 95
  • Sorry, my question wasn't complete by the time you answered. Now, I've updated live example. I also tried adding json filter, but it still shows empty object despite the fact that object is not empty. – Aleksandar Gajic Aug 03 '15 at 16:22
  • please check 2nd update, i also updated plnkr. Thanks! – Aleksandar Gajic Aug 03 '15 at 18:07
  • I added `console.log('Getting current position');` to the function `getCurrentPosition`, it is not even printed out. This function is not called correctly on my machine. I think it is another story other than `show Angular objects on view`. – Joy Aug 03 '15 at 23:43
0

I don't think your plunkr is related to a problem displaying prototypical objects, but more about displaying $location particularly.

After some debugging, it turns out that angular internally calls

angular.toJson($location)

And that call returns an empty object instead of the stringified version of the object. If you use JSON.stringify (which is used internally by angular, but with a replacer function that ignores variable names that start with '$' )

I modified your plunkr to manually stringify $location instead of calling angular.toJson.

Here's the modified plunkr: http://plnkr.co/edit/RszniTwU251lcXvJ3cFT?p=preview

Note how I added the following line in the controller:

 $scope.stringifiedLocation = JSON.stringify($location);

And this line in the view:

 <p>Stringified version ($scope.stringifiedLocation): {{stringifiedLocation}}</p>

Which produces the following output:

Stringified version ($scope.stringifiedLocation): {"$$protocol":"http","$$host":"run.plnkr.co","$$port":80,"$$path":"","$$search":{},"$$hash":"","$$url":"","$$absUrl":"http://run.plnkr.co/8NE1mySlQzBI1dLz/","$$state":null}

I also added a prototype object to try to answer the original question. JSON.stringify does not preserve any of the prototype properties of the object. More info in this SO question

EDIT to address your 2nd edit

It looks like objects such as Geolocation and File (and many others), cannot properly be stringified even with flattening. Here's some background as to why, taken from here:

File (and many others) are what used to be called host objects, parts of the platform mainly implemented in C++ --- they have JS bindings automatically generated from IDL files, like this https://github.com/WebKit/webkit/blob/master/Source/WebCore/fileapi/File.idl

Those properties are defined as accessors, and they'll try to invoke the accessors implemented in C++ --- the problem is that Object.create(File.prototype) isn't going to construct the C++ backend for this class, thus we don't really have these accessors, thus JSC decides to throw here (see https://github.com/WebKit/webkit/blob/master/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm#L2206-L2211 --- if it can't cast to the host object, it's gonna throw.

Community
  • 1
  • 1
yvesmancera
  • 2,915
  • 5
  • 24
  • 33