AngularJS scope.apply causes error - javascript

I have this function which fetches data from the DB and updates scope's values.
$scope.loadFromDB = function(){
console.log("loadFromDB function");
$http({
url: '/getData',
method: "GET",
})
.then(function(response) {
// success
var data = JSON.parse(response.data)
data = JSON.parse(data.data)
$scope.gridDataDayData = data.dayData;
$scope.gridDataKlasoveNames = data.klasoveNames;
$scope.gridDataNumOfRows = data.numOfRows;
$scope.$apply();
},
function(response) { // optional
// failed
console.log("get unsuccessful");
});
};
When I run this though I get
error: [$rootScope:inprog] http://errors.angularjs.org/1.4.3/$rootScope/inprog?p0=%24digest
I can not figure out how to fix this. Please help me.
Thank you

You don't need trigger the digest cycle because you are inside the angular life cycle... it is already running.
A manual triggering is needed when you are outside from the angular way: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

Simply remove
var data = JSON.parse(response.data)
data = JSON.parse(data.data) and $scope.$apply()
and
$scope.$apply();

Related

Not able to call method under success of api using .bind(this)

I am trying to call method on success of my ajax api call. I have stored this(context) inside local variable that but still not able to get context of that view and getting error that.setPdfUrl is not a function. And important thing is i am calling method by pub/sub mechanism.
My code looks like -
kf.Events.off('getPdfUrl');
kf.Events.on('getPdfUrl', this.getPdfUrl);
getPdfUrl: function() {
var that = this;
$.ajax({
url: kf.Settings.fileGeneratorUrl() + "/ikfc/singlereport",
type: 'POST',
data: {
//content
},
success: function(result) {
that.setPdfUrl(kf.Settings.fileGeneratorUrl() + '/download?guid=' +
result.Message);
}
});
}.bind(this),
setPdfUrl: function(url){
this.pdfUrl = url;
}
Getting
Uncaught TypeError: that.setPdfUrl is not a function
I got solution by binding context at initialize -
kf.Events.on('getPdfUrl', this.getPdfUrl.bind(this))
You can just move following lines.
getPdfUrl: function() {
var that = this;
Change to
var that = this;
getPdfUrl: function() {
it will work, there are multiple ways to achieve this. but for now, you can use this.

Angular setting variable as object through http

I'm trying to set a variable as the data object returned from a http request in angular, but the variable never sets to even if it is in the $scope unless it is nested within the success function. For example, if I do this in the controller :
$scope.hello = [];
var getAppointmentsurl = './dbscripts/getAppointments.php';
$http({method: 'GET', url: getAppointmentsurl}).success(function(data) {
$scope.hello = data;
});
console.log($scope.hello);
}
Hello is blank... so I set it up in services.js like this :
this.getCalendarData=function(){
var hello = [];
var getAppointmentsurl = './dbscripts/getAppointments.php';
$http({method: 'GET', url: getAppointmentsurl}).success(function(data) {
hello = data;
});
return hello;
}
but still hello is blank. Am I missing something obvious?
edit --
this.getCalendarData=function(){
var getAppointmentsurl = './dbscripts/getAppointments.php';
return $http({method: 'GET', url: getAppointmentsurl}).success(function(data) {
return data;
});
}
This is asynchronus call we have to return data like above.
To elaborate on Akash's correct answer, here's an example of how it should work.
In your view you should add logic to show the data only when hello exists. i.e. ng-if="hello"
controller:
ServiceName.getCalendarData().then(function(response) {
$scope.hello = response;
});
service:
this.getCalendarData = function() {
return $http.get('path/to/response/').success(function(data) {
return data;
});
}
As you put the api call as a method in the service, returning data from the service wont resolve yet, So in the controller the service return will only be a promise
serviceName.getCalendarData().then(function(data){
//Success data
},function(){});
Service code must return like the below code and here you will get the entire response object,
return $http({method: 'GET', url:getAppointmentsurl});
One other way to get the data directly resolved stripping of the other properties is returning from service like this,
return $http({method: 'GET', url:getAppointmentsurl}).success(function(data){
return data;
});

$scope doesn't get updated

The situation is like the code below. I want to change the value of $scope.pizzaList and $scope.selectedPizza when calling a function, but it seems not to change. I guess it is something with $scope's depth, but I'm not getting it. How to make these values get updated? Thanks in advance!
$scope.pizzaList = "some initial value";
$scope.selectedPizza = "some initial value";
$scope.setPizzaStatus = function (setStatus) {
$http.post('url1', { userID: $scope.pizzaioloID, pizzaID: $scope.selectedPizzaID, statusNum: setStatus }).
then(function(response) {
$http.get("url2")
.success(function (response) {
$scope.pizzaList = response;
});
$http.get("url3")
.success(function (response) {
$scope.selectedPizza = response[0];
});
}, function(response) {
console.log("Error");
});
}
$scope.pizzaList // doesn't get updated
$scope.selectedPizza // doesn't get updated
Try use $q.all():
$q.all([
$http.get("url2"),
$http.get("url3")
]).then(function(values){
$scope.pizzaList = values[0];
$scope.selectedPizza = values[1];//or values[1][0], It depends on data format;
}, function(error){
//error processing;
});
Don't forget add $q service to controller;
The way your code is written I would not expect the value of $scope.pizzaList to have changed between when you set it and when you evaluate it at the end. It will only be changed when you call the setPizzaStatus() method, and even then it will only change after the post to url1 and the get from url2 have returned from your server.
When you make a Get request, your Javascript code enters in "another task". So sometimes the current scope is not updated as expected. Try update the scope by calling "Apply", like this:
$http.get("url2")
.success(function (response) {
$scope.pizzaList = response;
$scope.$apply(); //or $scope.$applyAsync();
})

AngularJS : injecting data from factory to controller

I trying to get some data and then pass it to the controller for further processing. I have setup a factory to get the data but having issues passing it to the controller and getting it working. Below is the case I'm working with.
var app = angular.module("contactApp",[]);
app.factory('listData',function($http){
return{
getData: function(onSuccess,onFailure,itemID){
$http.get("/_api/web/lists/getbytitle('Consultant%20Profile')/items?$filter=ID%20eq%20"+itemID).success(onSuccess).error(onFailure);
}
};
});
app.controller('ContactController', function(listData,$scope){
//setTimeout(function(){console.log(Data)},2000);
console.log("Controller called. Hello");
listData.getData(successFunction,failFunction,curItemId);
successFunction = function(data){
$scope.resData = data;
console.log("Success - ", data);
}
failFunction - function(data){
console.log("Didn't work - ", data);
}
});
This gives me below error.
successFunction is not defined
Not sure what I'm doing wrong, any input will be greatly appreciated!
EDIT:
Moving the functions down works really well but the async call is failing. I switched to using $ajax and it works just fine but $http doesn't work for some reason!
app.factory('listData',function($http){
return{
getData: function(onSuccess,onFailure,itemID){
//$http.get("/_api/web/lists/getbytitle('Consultant%20Profile')/items?$filter=ID%20eq%20156").success(onSuccess).error(onFailure);
$.ajax({
url:"/_api/web/lists/getbytitle('Consultant%20Profile')/items?$filter=ID%20eq%20"+itemID,
headers: {"accept": "application/json; odata=verbose"},
success: onSuccess,
error: onFailure
});
}
};
});
Just fyi the data is coming from a SharePoint list but that shouldn't matter. I'll keep digging and please do let me know if I'm making any syntax error that I can't locate.
I really appreciate the help guys!
EDIT 2:
Ok this issue was unrelated. I found the problem, SharePoint uses odata so I had to pass a header:
app.factory('listData',function($http){
return{
getData: function(onSuccess,onFailure,itemID){
$http(
{
method: "GET",
headers: {"accept": "application/json; odata=verbose"},
url: "/_api/web/lists/getbytitle('Consultant%20Profile')/items?$filter=ID%20eq%20"+itemID
}
).success(onSuccess).error(onFailure);
}
};
});
You guys ROCK!!!!!!!
As Daniel A. White said, declare your functions before you call them.
var app = angular.module("contactApp",[]);
app.factory('listData',function($http){
return{
getData: function(onSuccess,onFailure,itemID){
$http.get("/_api/web/lists/getbytitle('Consultant%20Profile')/items?$filter=ID%20eq%20"+itemID).success(onSuccess).error(onFailure);
}
};
});
app.controller('ContactController', function(listData,$scope){
//setTimeout(function(){console.log(Data)},2000);
console.log("Controller called. Hello");
var successFunction = function(data){
$scope.resData = data;
console.log("Success - ", data);
}
var failFunction - function(data){
console.log("Didn't work - ", data);
}
//Now your functions are actually defined.
listData.getData(successFunction,failFunction,curItemId);
});
You don't have to use var to declare functions, because JavaScript will still understand but using var makes it a local variable, while not using var will define it as global.
I'm sure this will help.

Calling service function from within the same service

I am trying to call a service method from within the same service but I am getting call to undefined function error. So I made a work around as shown below but still wondering how I can call the service function without using the work around. So can someone please help by telling me what I am missing here? Thanks
.factory('TestSvc', function($http, $q) {
return {
login: function(){
var checkStatusFunction = this.checkstatus; //This is the workaround to make it work...
$http({ method:'POST',
url: url
responseType: 'json'
}).success(function(data,status,headers,config){
//this.checkStatus(); //this will return error call to undefined
checkStatusFunction(); //this will work as it is the work around
}).error(function(data,status,headers,config){
});
},
checkStatus: function(){
}
}
});
A little bit less hacky would be:
var $this = this;
Instead of:
var checkStatusFunction = this.checkstatus;
And then call:
$this.checkstatus();

Categories