Reputation: 1240
I have written a custom angular directive as shown below:
dirs.directive('sectionInfo', function(){
return {
restrict: 'E',
templateUrl: 'partials/section-home.html',
transclude: true,
controller: function($scope, $routeParams){
var section = this;
section.sectionItem = [];
client.entries({"some params"},
function(err, entries){
if (err) { console.log(err); return; }
$scope.$apply(function(){
section.sectionItem = entries;
});
}
);
},
controllerAs: 'sectionCtrl'
}
});
This is then displayed in a separate partial page which looks like:
<section-info></section-info>
<ul class="list-group">
<li class="list-group-item" ng-repeat="entry in entriesCtrl.index_items">
<a href="#/entries/{{entry.sys.id}}">
<h4>{{entry.fields.title}} <small>{{entry.fields.author}}</small></h4>
</a>
</li>
</ul>
With the partial template code being simply:
{{sectionCtrl.sectionItem}}
When I load this page and keep the $scope$apply call in then I get an error:
Error: error:interr Interpolation Error Can't interpolate: {{sectionCtrl.sectionItem}} TypeError: Converting circular structure to JSON
When I remove the $scope.$apply call it disappears. Any idea what is causing the circular reference within the $scope.$apply call?
EDIT: Console log of content of entries and the error message.
Upvotes: 2
Views: 3751
Reputation: 5070
What's happening is you have a circular reference, meaning an object is referring to itself, through one of its properties or elements. ( In your picture, it looks like the sys
field is referencing to its parent object ). To illustrate here's a sample with an object that references itself through a field, you can't convert this to regular JSON. This'll alert the error.
angular.module("so", []);
console.error = function(msg){
console.log("Well, an error occurred, here's what it said:" + msg);
}
angular.module("so").controller("AnswerCtrl", function($scope){
// make a thing, and put the thing in itself
$scope.thing = { somefield: 'lalalala' };
$scope.thing.circle= $scope.thing;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="so" ng-controller="AnswerCtrl">
{{ thing }}
</div>
So the problem isn't very much related to Angular, but more that angular is using JSON.stringify
or something along those lines to convert the object to a JSON string so that it can display it in the view.
What you can do is, first off - do not try to display the actual object with the circular reference. You can display parts of it just fine, but don't try to serialize a cyclic object to JSON.
If you want to display all properties though, you can use something like this answer, demoed here:
angular.module("so", []);
console.error = function(msg){
console.log("Well, an error occurred, here's what it said:" + msg);
}
angular.module("so").controller("AnswerCtrl", function($scope){
// make a thing, and put the thing in itself
$scope.thing = { somefield: 'lalalala' };
$scope.thing.circle= $scope.thing;
var cache = [];
$scope.viewThing = JSON.stringify($scope.thing, function(key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
return;
}
cache.push(value);
}
return value;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="so" ng-controller="AnswerCtrl">
{{ viewThing }}
</div>
If you have to display it, use this libary for it.
Upvotes: 4
Reputation: 1359
Try something like this:
var safeApply = function (scope, callback) {
if (scope.$$phase != '$apply' && scope.$$phase != '$digest' &&
(!scope.$root || (scope.$root.$$phase != '$apply' && scope.$root.$$phase != '$digest'))) {
scope.$apply();
}
if (angular.isFunction(callback)) {
callback();
}
};
and you can call this
safeApply($scope, function(){
section.sectionItem = entries;
});
Upvotes: 1