$digest already in progress - javascript

I'm fetching the data using $http.get() and passing it as argument to a custom filter to get the filterd data. But it is giving an
error: $digest already in progress.
Does anyone know how to avoid this error or achieve the same thing but a different way?
var map=angular.module('map', [])
.controller('mapCtrl', function ($scope,$filter,$http) {
$http.get('./json/integrated.json').success(function(data) {
$scope.sitesInfo = data;
});
var filteritems= $filter('applySfotwareFilter')($scope.sitesInfo);
});

I think you should place
var filteritems= $filter('applySfotwareFilter')($scope.sitesInfo);
inside your success function;
What happens is the filtering starts before your data is ready.

Related

How to get variables out of a get odata call method

What is the best way to get variables out of a get odata call. I have this code in a method where i want to work with the variable 'id', which i am getting with the odata call. I tried already callbacks but i cant get the right way. Do you have a solution for this? I tried also to put the call in an extra function, but then i get the problem that by return variable is undefined i a cant access it.
Update / additional:
I have a method where i am doing some odata updates and inserts. in my code below i am getting a id. this id i need in the next step for another odata update as parameter. My problem is that i cant work with the var id in the next steps of my code, because its only accessable in the oModel {} section.
oModel.read("/ZDEMA_LENDINGS2Set", {
urlParameters: {
"$select": "Id",
"$top": 1
},
success: function(oData, oResponse) {
console.log("Data", oData);
console.log("Response", oResponse);
var id = oData.results[0].Id;
},
error: function(oError) {
console.log("Error", oError);
}
}
Since this an UI5 app, I suggest using a local JSON Model and set the value as property.
this.getView().getModel('myLocalModel').setProperty("lendingId", oData.results[0].Id)
This has the advantage that you can use the two way databinding and or change listeners.
Alternative approach is to fire an event on the event bus.

Angularjs Scope Variable does not Update View

I have seen this issue a lot on SO, but none of the solutions I have tried are working for me. I tried using $apply() which gives me an error stating that the digest cycle is already running. I tried using the Dot "." notation, but nothing changes. I even tried using timeout and promises, but still it does not update in the view.
Here is the HTML:
<th colspan="4" ng-class="{'ssqtrue': deficiencies === false , 'ssqfalse': deficiencies === true}">
<span ng-model="definfo">{{definfo}}</span>
</th>
Here is my Controller code:
$scope.recalculateDashboard = function (goToDashboard) {
contractorService
.calculateScores()
.success(function () {
getscoringDetails();
getDefInfo();
if (goToDashboard) {
$scope.tabs[0].active = true;
}
}).error(function (reason) {
console && console.log(reason.statusText);
genericErrorAlertHandler();
});
};
function getDefInfo() {
contractorService.getDeficiencyInfo()
.success(function (data) {
$scope.$apply(function() {
$scope.definfo = data;
});
if ($scope.definfo == 'No Deficiencies Found') {
$scope.deficiencies = false;
} else {
$scope.deficiencies = true;
}
}).error(function (reason) {
console && console.log(reason.statusText);
genericErrorAlertHandler();
});
}
For the life of me, I can't figure out what is going on here. Any assistance is greatly appreciated!
Regards to <span ng-model="definfo">{{definfo}}</span>
You don't need ng-model directive here. Enough to use {{definfo}} or better way like folks pointed to use ng-bind like:
<span ng-bind="definfo"></span>
I tried using $apply() which gives me an error
Generally, developers use $scope.$apply when get callback from 3d party code like jQuery that stay out of digest cycle. So don't use it. BTW, safety way is to use $timeout for example a.e. wrap as:
$timeout(function () {
$scope.definfo = data;
});
I believe if you don't use Promise chain you can use success and error callbacks (what you actually did) instead to use then()
About $http.get('/SSQV4/SSQV5/Contractor/GetDeficiencyInfo');
$http.get returns original Promise but it also returns status 'Ok', config, headers ... and i'm sure you don't want parse full response in your controller.
So I would create new Promise in your service and fetch results only.
So instead: return $http.get(URL); I would write in Service:
this.getDeficiencyInfo = function () {
var deferred = $q.defer();
$http({method: 'GET', url: URL}).then(function(res){
deferred.resolve(res.data);
}, function (error) {
console.error(error);
deferred.resolve({error:error}); //actually you can reject
});
return deferred.promise;
};
DEMO in fiddle
I figured this out, although I don't know "why" it caused this particular issue. When the page first loads $scope.definfo is set by a variable from another http call. The variable var pagedata = [] holds a lot of information that comes back from the service when the page is first rendered. The scope variable is then set with this code: $scope.definfo = pagedata.DeficiencyInfo. Removing that line and calling the function getDefInfo directly, sets and updates the scope variable as desired. Perhaps one of you gurus could explain why that is to me and others so that it may help others. Thank you to everyone for your help.

AngularJS: How to update $scope after a promise response?

Disclaimer: I'm a beginner with AngularJS.
I'm trying to update $scope after a promise has returned, but it does not work. Here's the simplified code:
.controller('ChooseRewardCtrl', ['$scope', ...,
function($scope, ...) {
// scope data
$scope.points = CardModel.points;
// function called to refresh points
$scope.refresh_points = function() {
return CardModel.refresh_points() // This is a promise that changes CardModel.points value
.then(function(data){
$scope.$apply() // Throw error (cf. above)
})
}
}
I get a Error: [$rootScope:inprog] $digest already in progress
I saw lots of post about this error, but nothing that I can directly link to my problem.
Thanks!
Try this:
.then(function(data){
$scope.points = CardModel.points;
})
you need not use $apply().
log your function parameter ('data') and see what does it contain.
It should contain value returned by promise.
assign the appropriate value to your scope variable.

Variable scope when using $http service in AngularJS

I'm hoping someone can shed some light on the scope of variables when using the $http AngularJS service.
My code looks like this:
app.controller('TestPlanRequestCtrl', function($scope, $http) {
$scope.tableData = []; // Populate the table with this array
$scope.tpRequests = null;
$http.get('common/data/requests.json').success(function(data) {
$scope.tpRequests = data.TPRequests;
});
Next I want to run a loop to put my data into an array like so:
for (var i = 0; i < $scope.tpRequests.length; ++i) {
var requestObj= {
requestNum: $scope.tpRequests[i].RequestNumber;
}
$scope.tableData.push(requestObj);
}
This works great if the for loop is inside the function called from the success method, but I think it would be cleaner to keep it outside the call. If I have the loop outside the call, I get the error:
Error: $scope.tpRequests is null
I don't understand why tpRequests is populated in the get call, and then the data is gone after the get call ends. I'm guessing it is considering the $scope.tpRequests inside the function call to be a different one than the one I declared above the $http.get(). What's the correct way to do this?
You can use a $watch on $scope.tpRequests to do your data manipulation, however I would recommend just doing it in the success promise if there are no other ways to trigger the watch and simply check for null/undefined before operating.
A great primer on use cases for $watch and $watchCollection:
http://www.bennadel.com/blog/2566-scope-watch-vs-watchcollection-in-angularjs.htm

executing Angular JS code after some jQuery.ajax has executed

I want to update an Angular scope with data returned by some jQuery ajax call. The reason why I want to call the Ajax from outside Angular is that a) I want the call to return as fast as possible, so it should start even before document.ready b) there are multiple calls that initialize a complex model for a multiple-page web app; the calls have dependencies among themselves, and I don't want to duplicate any logic in multiple Angular controllers.
This is some code from the controller. Note that the code is somewhat simplified to fit here.
$scope.character = {};
$scope.attributeArray = [];
$scope.skillArray = [];
The reasoning for this is that a character's attributes and skills come as objects, but I display them using ng-repeat, so I need them as arrays.
$scope.$watch('character',function(){
$scope.attributeArray = getAttributeArray($scope.character);
$scope.skillArray = getSkillArray($scope.character);
});
In theory, when $scope.character changes, this piece of code updates the two arrays.
Now comes the hard part. I've tried updating $scope.character in two ways:
characterRequestNotifier.done(function() { // this is a jQuery deferred object
$scope.$apply(function(){ // otherwise it's happening outside the Angular world
$scope.character = CharacterRepository[characterId]; // initialized in the jquery ajax call's return function
});
});
This sometimes causes $digest is already in progress error. The second version uses a service I've written:
repository.getCharacterById($routeParams.characterId, function(character){
$scope.character = character;
});
, where
.factory('repository', function(){
return {
getCharacterById : function(characterId, successFunction){
characterRequestNotifier.done(function(){
successFunction( CharacterRepository[characterId] );
});
}
};
});
This doesn't always trigger the $watch.
So finally, the question is: how can I accomplish this task (without random errors that I can't identify the source of)? Is there something fundamentally wrong with my approaches?
Edit:
Try this jsfiddle here:
http://jsfiddle.net/cKPMy/3/
This is a simplified version of my code. Interestingly, it NEVER triggers the $watch when the deferred is resolved.
It is possible to check whether or not it is safe to call $apply by checking $scope.$$phase. If it returns something truthy--e.g. '$apply' or '$digest'--wrapping your code in the $apply call will result in that error message.
Personally I would go with your second approach, but use the $q service--AngularJS's promise implementation.
.factory('repository', function ($q) {
return {
getCharacterById : function (characterId) {
var deferred = $q.defer();
characterRequestNotifier.done(function () {
deferred.resolve(CharacterRepository[characterId]);
});
return deferred.promise;
}
};
});
Since AngularJS has native support for this promise implementation it means you can change your code to:
$scope.character = repository.getCharacterById(characterId);
When the AJAX call is done, the promise is resolved and AngularJS will automatically take care of the bindings, trigger the $watch etc.
Edit after fiddle was added
Since the jQuery promise is used inside the service, Angular has no way of knowing when that promise is resolved. To fix it you need to wrap the resolve in an $apply call. Updated fiddle. This solves the fiddle, I hope it solves your real problem too.

Categories

Resources