Getting undefined data when i called a service - javascript

So I have a question that i've been trying to solve for hours.
My problem is that I'm getting the data faster than my services to load.
gen-service
function genEmpId() {
settingsService.getSettings().then(function (data) {
var comId = data.data[0].companyId;
console.log(comId);
var test = comId + ' - ';
return test;
});}
controller
function genId() {
var data = genService.genEmpId();
console.log(data); // getting the data too fast how to put a callback ?
}
So when my controller load its calling the service but im getting an undefined return value.

try this, In your code you not returning anything and another thing is it's async call to you have to wait until it finishes.
// gen-service
function genEmpId() {
return settingsService.getSettings().then(function (data) {
var comId = data.data[0].companyId;
console.log(comId);
var test = comId + ' - ';
return test;
});
}
// controller
function genId() {
var data = genService.genEmpId().then(function (data) {
console.log(data);
})
}

Related

How to return value from an ajax call function

I have a function
function GetITStaffList(){
var go_path = "Server/ITComplains.php?action=GetITStaffList&vars=0";
$jqLibrary.get(go_path,
{}, function(data)
{
var parseData = JSON.parse(data);
console.log("GetPendingAndInProgressComplainsByGeneratorId : ", parseData);
return parseData;
});
}
I am calling this somewhere in the code like this
var ITStaffList = GetITStaffList();
MakeDropDownITStaff(ITStaffList);
But the problem is each time it is returning null. I know that I have to use callback and something like a promise but I don't how to fit this thing in my context. How do I write a reusable function with ajax call that returns data on demand.?
Return a promise instead.
function GetITStaffList(){
return new Promise(function(resolve){
var go_path = "Server/ITComplains.php?action=GetITStaffList&vars=0";
$jqLibrary.get(go_path,
{}, function(data)
{
var parseData = JSON.parse(data);
console.log("GetPendingAndInProgressComplainsByGeneratorId : ", parseData);
resolve(parseData); //Notice this
});
})
}
Now you can call the function and wait for data.
GetITStaffList().then(function(data){
console.log(data)
})

Update field when function finishes its calculations

I got this function that calls an external service, works the results and then returns a single variable.
I want this variable to be inserted into an input but I'm doing something wrong cause instead of updating the form at the end of the function (as expected) I have to call the function a second time and the code updates the field with the value of the FIRST execution...
This is the controller:
$scope.cercaClienteNomeCognome = function() {
if ($scope.nome == undefined){
var name = "";
} else name = angular.uppercase($scope.nome);
if ($scope.cognome == undefined){
var surname = "";
} else surname = angular.uppercase($scope.cognome);
var url = "servizi/getClienteNomeCognome?nomeCliente="+name+"&cognomeCliente="+surname;
esitoRicercaEstesa = TreeService.avviaRicercaEstesa(url);
if (esitoRicercaEstesa == "true") {
vm.cercaSecondario = TreeService.getProClie(); // THIS_LINE
}
};
vm.cercaSecondario is the field that I'm trying to update.
This is the service:
service.avviaRicercaEstesa = function(url) {
service.url = url;
$http.get(url)
.success(function(data, status, headers, config) {
service.apriModaleEstensioneRicerca(data);
})
.error(function(data, status, headers, config) {
toaster.error("[SERVIZIO RECUPERO CLIENTI] Errore durante il ritrovamento dei clienti");
});
}
service.setProClie = function (pro_clie) {
service.pro_clie = pro_clie;
}
service.getProClie = function () {
return service.pro_clie;
}
Example: I run the code for the FIRST time. Everything goes fine.
When I get to THIS_LINE the field doesn't update.
I then run the code for the SECOND time and when I get to THIS_LINE the field updates with the value from the FIRST execution......
What am I doing wrong?!
I've even tried using $timeout and $evalASync but with no success...
Maybe your service caused this problem. Try to use $q and return promise from your service. Then use it like this
$scope.cercaClienteNomeCognome = function() {
if ($scope.nome == undefined){
var name = "";
} else name = angular.uppercase($scope.nome);
if ($scope.cognome == undefined){
var surname = "";
} else surname = angular.uppercase($scope.cognome);
var url = "servizi/getClienteNomeCognome?nomeCliente="+name+"&cognomeCliente="+surname;
esitoRicercaEstesa = TreeService.avviaRicercaEstesa(url);
if (esitoRicercaEstesa == "true") {
TreeService.getProClie().then(function (cercaSecondario) {
vm.cercaSecondario = cercaSecondario;
});
}
};
My bet would be that your remote call will make your code to be "out of angular context" so what happens is that by the time you get your response from your remote call angular won't know this and won't digest. So you either need to manually call $scope.$digest() after vm.cercaSecondario = TreeService.getProClie(); or you can wrap your remote call into $q.when(remoteCall).then(...). This way angular will digest by it's own.
Try like this:
TreeService.getProClie()
.then(function(res){
vm.cercaSecondario = res;
})
EDIT:
This to work you have to set your service to return promise.
.service('TreeService', function($q){
var data = this;
data.getProClie = function(){
var defer = $q.defer();
$http.get('example/url')
.success(function(res){
defer.resolve(res)
})
.error(function(error,status){
defer.reject(error);
})
return defer.promise;
};
})
write getProClie function in this way.
You need to promise chaining
service.getProClie = function () {
var defer = $q.defer();
defer.resolve(service.pro_clie);
return defer.promise;
}
Then in controller :
TreeService.getProClie().then(function(data){
vm.cercaSecondario = data
},
function(){
//error handling
});

Angular function in service not seen as a function

I have been trying to move a bunch of code into a service instead of having it sit in the controller because other controllers in my application are going to need some of the same functionality. I have the following controller code:
JBenchApp.controller('CaseListCtrl', ['$scope', '$http', 'HoldState',
function ($scope, $http, HoldState) {
//----------------------------------------------------------
// Load the Calendar Data whent he department changes
//----------------------------------------------------------
$scope.getCalendarOnDeptChange = function () {
// Get the dropdown into e
var e = document.getElementById("deptSelect");
// Set $scope.department to the text of the selected dropdown item --- MUST FIND BETTER ANGULAR METHOD
$scope.department = e.options[e.selectedIndex].text;
console.log($scope.department);
$scope.getCalendar();
};
//----------------------------------------------------------
// Load the calendar data
//----------------------------------------------------------
$scope.getCalendar = function () {
// Retrieve calendar data
HoldState.getCalendar($scope.lastDepartment, $scope.date, $scope.lastLawType, $scope.lastLocationID).then(function (data) {
$scope.cases = data;
$scope.$apply();
});
HoldState.setDepartment($scope.department);
};
//----------------------------------------------------------
// Load the user's default settings
//----------------------------------------------------------
$scope.loadDefaults = function () {
HoldState.getUserDefaults($scope.UserID).then(function (data) {
$scope.UserDefaults = data;
});
$scope.defaultDepartment = $scope.UserDefaults.CourtRoom;
$scope.defaultLawType = $scope.UserDefaults.LitigationCode;
$scope.defaultLocationID = $scope.UserDefaults.LocID;
};
$scope.loadPaths = function () {
HoldState.getTypeOfLaw().then(function (data) {
$scope.lastLawType = data;
});
HoldState.getCourthouse().then(function (data) {
$scope.lastLocationID = data;
});
HoldState.getDepartment().then(function (data) {
$scope.lastDepartment = data;
});
};
$scope.doAuthentication = function () {
$scope.UserID = 'dpeng';
};
$scope.saveSequence = function () {
};
//----------------------------------------------------------
// Initial processing
// Located here so that all functions are defined before
// being called.
// 1. Authenticate the user
// 2. Get the default values
// 3. Load the paths
// 4. Get the list of departments
// 5. Show the calendar.
//----------------------------------------------------------
$scope.doAuthentication();
$scope.loadDefaults();
$scope.loadPaths();
HoldState.getDepartmentList($scope.lastLawType, $scope.lastLocationID).then(function (data) {
$scope.departments = data;
});
$scope.getCalendar();
}]);
I also have the following service code:
var StateService = angular.module('StateService', [])
.service('HoldState', function ($http) {
this.setTypeOfLaw = function (a) { localStorage.setItem('LawType', a) };
this.setCourthouse = function (a) { localStorage.setItem('Building', a) };
this.setDepartment = function (a) { localStorage.setItem('Dept', a) };
this.getTypeOfLaw = function () {
var LT = localStorage.getItem('LawType');
return LT;
};
this.getCourthouse = function () {
var BLDG = localStorage.getItem('Building');
return BLDG;
};
this.getDepartment = function () {
var DEPT = localStorage.getItem('Dept');
return DEPT;
};
this.setStatus = function (a) { localStorage.setItem('Status', a) };
this.getStatus = function () {
var STATUS = localStorage.getItem('Status');
return STATUS;
}
//Begin default settings
this.getUserDefaults = function (UserID) {
var userDefaults = [];
$http.get('http://10.34.34.46/BenchViewServices/api/UserPreference/Default/' + UserID)
.then(function (response) {
userDefaults = response;
var status = this.getStatus();
// If the status is 0 then we have not yet navigated anywhere so we will need to set the path values to be
// the same as the default. We do nothing if status is not 0 because it means we already have path values set
if (status == 0) {
this.setTypeOfLaw(response.LitigationCode);
this.setCourthouse(response.LocID);
this.setDepartment(response.CourtRoom);
}
}, function (response) {
console.log(response.status + " -- " + response.data + " -- " + response.statusText);
});
return userDefaults;
};
When I call $scope.loadDefaults(); I get an error that says:
TypeError: HoldState.getUserDefaults(...).then is not a function
at m.$scope.loadDefaults (http://localhost:54365/js/controllers.js:78:52)
at new <anonymous> (http://localhost:54365/js/controllers.js:121:14)
at Object.e [as invoke] (http://localhost:54365/js/angular.min.js:36:315)
at x.instance (http://localhost:54365/js/angular.min.js:76:79)
at http://localhost:54365/js/angular.min.js:59:85
at q (http://localhost:54365/js/angular.min.js:7:428)
at M (http://localhost:54365/js/angular.min.js:59:69)
at g (http://localhost:54365/js/angular.min.js:51:409)
at http://localhost:54365/js/angular.min.js:51:17
at chrome-extension://ighdmehidhipcmcojjgiloacoafjmpfk/dist/hint.js:2071:22 <div ng-view="" class="view-frame ng-scope">(anonymous function) # angular.min.js:102
angular.min.js:102 TypeError: Cannot read property 'getStatus' of undefined
at controllers.js:311
at angular.min.js:112
at m.$eval (angular.min.js:126)
at m.$digest (angular.min.js:123)
at m.scopePrototype.$digest (chrome-extension://ighdmehidhipcmcojjgiloacoafjmpfk/dist/hint.js:1955)
at m.$apply (angular.min.js:127)
at m.scopePrototype.$apply (chrome-extension://ighdmehidhipcmcojjgiloacoafjmpfk/dist/hint.js:2018)
at l (angular.min.js:81)
at P (angular.min.js:85)
at XMLHttpRequest.H.onload (angular.min.js:86)(anonymous function) # angular.min.js:102
What have I done wrong? I am merely trying to cleanly get back the data from a web service through my Angular service.
getUserDefaults is the only method that really needs to be a promise, as you are making an async call to your api. So, inject $q into your service and then have that method return a promise.
this.getUserDefaults = function (UserID) {
var userDefaults = [], deferred = $q.defer();
$http.get('http://10.34.34.46/BenchViewServices/api/UserPreference/Default/' + UserID)
.then(function (response) {
var status = this.getStatus();
// If the status is 0 then we have not yet navigated anywhere so we will need to set the path values to be
// the same as the default. We do nothing if status is not 0 because it means we already have path values set
if (status == 0) {
this.setTypeOfLaw(response.LitigationCode);
this.setCourthouse(response.LocID);
this.setDepartment(response.CourtRoom);
}
d.resolve(response);
}, function (response) {
console.log(response.status + " -- " + response.data + " -- " + response.statusText);
});
return deferred.promise;
};
you also should just use the getters as getters, and not try to treat them as promises.
i.e.
$scope.loadPaths = function () {
$scope.lastLawType = HoldState.getTypeOfLaw();
$scope.lastLocationID = HoldState.getCourthouse();
$scope.lastDepartment = HoldState.getDepartment();
};
This should fix the problem
$scope.loadDefaults = function () {
HoldState.getUserDefaults($scope.UserID).then(function (data) {
$scope.UserDefaults = data;
}, function(errData) {
//$scope.UserDefaults isn't going to get filled, so do some error handling here.
});
$scope.defaultDepartment = $scope.UserDefaults.CourtRoom;
$scope.defaultLawType = $scope.UserDefaults.LitigationCode;
$scope.defaultLocationID = $scope.UserDefaults.LocID;
};
And
//Begin default settings
this.getUserDefaults = function (UserID) {
//Here we return the promise
return $http.get('http://10.34.34.46/BenchViewServices/api/UserPreference/Default/' + UserID)
.then(function (response) {
userDefaults = response;
var status = this.getStatus();
// If the status is 0 then we have not yet navigated anywhere so we will need to set the path values to be
// the same as the default. We do nothing if status is not 0 because it means we already have path values set
if (status == 0) {
this.setTypeOfLaw(response.LitigationCode);
this.setCourthouse(response.LocID);
this.setDepartment(response.CourtRoom);
}
//Here we fill the data variable
return response;
}, function (response) {
console.log(response.status + " -- " + response.data + " -- " + response.statusText);
});
};
Take another look at the error:
HoldState.getUserDefaults(...).then is not a function
^^^^
HoldState.getUserDefaults() doesn't return a promise, that's the problem.
To be able to consume the service like you are at the moment, tweak the method a little:
this.getUserDefaults = function (UserID) {
return $http.get('http://10.34.34.46/BenchViewServices/api/UserPreference/Default/' + UserID)
.then(function (response) {
var status = this.getStatus();
// If the status is 0 then we have not yet navigated anywhere so we will need to set the path values to be
// the same as the default. We do nothing if status is not 0 because it means we already have path values set
if (status == 0) {
this.setTypeOfLaw(response.LitigationCode);
this.setCourthouse(response.LocID);
this.setDepartment(response.CourtRoom);
}
}, function (response) {
console.log(response.status + " -- " + response.data + " -- " + response.statusText);
});
};
Since promises are chainable, you are essentially returning the promise you get from $http.get(), which will be resolved with response. This should make it work.

Add Async REST Call JSON to Angular $scope

I need some help understanding how to structure an AngularJS controller.
The controller is to execute an Async REST call to SharePoint and put the JSON results into a $scope.SearchResults property.
The Async REST call is executed by the getDataSP() function and the $scope.SearchResults is assigned in the onQuerySuccess() callback. The onQuerySuccess() method has the statement
console.log('Search Results Returned.' + $scope.SearchResults);
which does display the expected "[object Object]" so I know it is returning something.
However the HTML page has the following tag to show the JSON object. I also expect it to display "[object Object]" but it never shows up!
<span >{{SearchResults}}<span>
Here is the code for the entire module.
(function () {
var app = angular.module('FormApp', []);
app.controller('FormController', ['$scope', function ($scope) {
var context = SP.ClientContext.get_current();
var user = context.get_web().get_currentUser();
function onQuerySuccess() {
if (results && results.m_value && results.m_value.ResultTables && results.m_value.ResultTables[0] && results.m_value.ResultTables[0]) {
$scope.SearchResults = results.m_value.ResultTables[0];
console.log('Search Results Returned.' + $scope.SearchResults);
} else {
results = {};
console.log('Search Results Failed');
}
}
function onQueryFail(sender, args) {
console.log('Query failed. Error:' + args.get_message());
}
function getDataSP() {
var keywordQuery = new Microsoft.SharePoint.Client.Search.Query.KeywordQuery(context);
keywordQuery.set_queryText("*");
keywordQuery.set_sourceId("d0aa2c2e-7709-46f1-835a-244f483e4b0e");
var managedProperties = ['RefinableString00'];
var kwqProperties = keywordQuery.get_selectProperties();
for (var i = 0; i < managedProperties.length; i++) {
kwqProperties.add(managedProperties[i]);
}
var searchExecutor = new Microsoft.SharePoint.Client.Search.Query.SearchExecutor(context);
results = searchExecutor.executeQuery(keywordQuery);
context.executeQueryAsync(onQuerySuccess, onQueryFail)
};
getDataSP();
$scope.ProjectSelected = function (proj) {
$scope.SelectedProj = proj;
};
}
]);
angular.bootstrap(document.body, ['FormApp']);
})();
you need to notify Angular that you changed the model. Usually when your code is triggered or the callback handled by Angular, it checks automatically, but in this case, it doesn't know anything about your callback. You can do this simply by calling $scope.$apply() at the end of your callback.
some more info: https://github.com/angular/angular.js/wiki/When-to-use-$scope.$apply()

Javascript scope error when accessing from callback

Below is part of code from angularjs service. It may not a specific question to angular though.
The $http.get('/api/test/1').then ( ... returns promise and I like to process the data returned by the call back. I am getting error when accessing filter method.
Test.filter(data.Root);
TypeError: Object #<Object> has no method 'filter'
But, I could access the data variable in the same scope (previous line) though.
var testApp = angular.module('testApp.services', []);
testApp.factory('Test', function ($http, $rootScope) {
var Test = {};
var data = [];
Test.filter = function (d) {
ret = data.filter(function (el) {
return el.Pid == d.Id;
});
return ret;
};
Test.data = function () {
return data[1];
};
Test.start = function () {
Test.asyncData = $http.get('/api/test/1')
.then(function (response) {
data = response;
return Test.filter(data.Root);
}, function (response) {
Test.error = 'Can\'t get data';
data = 'Error: ' + response.data;
return data;
});
};
return Test;
});
I think your error is coming from:
ret = data.filter(...
The data variable, which you set to the response, doesn't have a filter method.
It is probably either not of the type you think it is, or you meant to call the filter method on something else.

Categories

Resources