I'm still quite new to Angular (1) and do keep having $scope issues. It's probably very easy to resolve but I can't seem to figure it out myself and keep struggling to keep my $scope updated.
Say I've the following code
.controller('PostsCtrl', function ($scope, $http, $timeout, PostService) {
$scope.items = [];
PostService.getAll().then(function(data) {
var remoteItems = data;
for (var i = 0; i < remoteItems.length; i++) {
var object = {};
object.title = remoteItems[i].title;
object.id = remoteItems[i]._id;
$scope.items.push(object);
}
});
})
As you can see I've created a little service that does make the actual request to my backend. I use a promise and provide a callback function.
Now, because I update $scope.items
inside the callback, it doesn't update the $scope inside the controller because of different scopes.
when adding a $scope.$apply
I get $digest already in progress
error messages in my browser's JavaScript console. This should be solved by wrapping the apply function in a $timeout
function. This resolves the error messages but doesn't give me the desired output. I read that when I get these $digest already in progress
error messages, the architecture of my application is wrong, though I couldn't find how my architecture should be changed to resolve this.
How can I resolve this? Or better said, what's the best practice to resolve this? I kind of think this is something that happens quite a lot in most Angular applications :) .
I've created a Plunker that's similar to my code, though I do not know how to work around the $http request... Link here: https://plnkr.co/edit/rhWhgCgfV0kA1frM41xL
Thanks for your help in advance!
PostService.getAll().then(function(data) {
var remoteItems = data;
var returnedData = [];
for (var i = 0; i < remoteItems.length; i++) {
var object = {};
object.title = remoteItems[i].title;
object.id = remoteItems[i]._id;
returnedData.push(object);
}
$scope.$apply(function() {
$scope.items = returnedData;
});
});
You can use safeApply
to avoid "$digest already in progress"
Declaration :
angular.module('yourApp').run(function ($rootScope) {
/* safe scope apply to avoid "digest already in"
* $rootScope.$safeApply(fctA());
* */
$rootScope.$safeApply = function () {
var $scope, fn, arg, force = false, args = arguments;
if (args.length === 1) {
arg = args[0];
if (typeof arg === 'function') {fn = arg;} else { $scope = arg; }
} else if (args.length > 0) {
$scope = args[0]; fn = args[1];if (args.length === 3) {force = !!args[2]; }
}
$scope = $scope || this || $rootScope;
if ($scope === window) { $scope = $rootScope; }
fn = fn || function () {};
if (force || !($scope.$$phase || $scope.$root.$$phase)) {$scope.$apply ? $scope.$apply(fn) : $scope.apply(fn);} else { fn(); }
};
})
Usage ( don't forget to inject $rootScope
in your controllers )
$rootScope.$safeApply(aFunction());
// or
$rootScope.safeApply( $scope );
EDIT : look at this module also
Ugh, I feel stupid but I found the issue. The issue wasn't the callback function. The Plunker proved this. What I didn't recreate was the partial HTML's that I also use in my application.
A closer look on where I included those partials in the main HTML showed that those were out of scope of where I set the controller. To show with code:
<div ng-controller="testController">
<!-- Do things here -->
</div
<!-- Partials go here -->
<div>
</div>
Is now this:
<div ng-controller="testController">
<!-- Do things here -->
<!-- Partials go here -->
<div>
</div>
</div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.