$http get response data issue when saving to a scope variable - javascript

Below is the code that has some issue in assigning return values to the scope variable.
app.factory("appService",function($http){
var promise;
var lists = {
async: function() {
var promise = $http.get("http://localhost:81/hrms/public/languagesService").then(function (response) {
return response.data;
});
return promise;
}
};
return lists;
});
The response from the $http get is successful with status code 200. Below is the code, using the above service in the controller
app.controller("AppCtrl",function(appService,$scope,$http,$filter) {
$scope.language = "";
var sortingOrder = 'id';
$scope.sortingOrder = sortingOrder;
$scope.reverse = false;
$scope.filteredItems = [];
$scope.groupedItems = [];
$scope.itemsPerPage = 4;
$scope.pagedItems = [];
$scope.currentPage = 0;
$scope.items = [];
$scope.itemlist = function() {
appService.async().then(function(d){
$scope.data = d;
});
}
$scope.items = $scope.itemlist();
But the $scope.items is empty. please guide me how to pass values to $scope.items. i have also tried $scope.items.push(d), but nothing seems to work...
All i want is to have $scope.items to hold the response data from $http.get().

I guess, the response is array. So you can return empty array, and then fill it with data, after response will be delivered:
$scope.itemlist = function() {
var result = [];
appService.async().then(function(d){
$scope.data = d;
result.push.apply(result,d);
});
return result;
};
$scope.items = $scope.itemlist();
Here we use apply method to push multiple elements at once.

Hi why don't you just assign d to $scope.items as follows
app.controller("AppCtrl",function(appService,$scope,$http,$filter) {
$scope.language = "";
var sortingOrder = 'id';
$scope.sortingOrder = sortingOrder;
$scope.reverse = false;
$scope.filteredItems = [];
$scope.groupedItems = [];
$scope.itemsPerPage = 4;
$scope.pagedItems = [];
$scope.currentPage = 0;
$scope.items = [];
appService.async().then(function(d){
$scope.items = d;
});
})

Related

How to add a $scope object value to another $scope object? (AngularJS)

I'm taking the data from different sharepoint pages lists. I'm calling these lists with a Factory.
My code is counting how many items with a "Completed" status each list has.
I need to take the values of each one into an array, but the result is always null.
Here's my example:
<script>
var myApp = angular.module("myApp", []);
myApp.factory("myFactory", ["$http", function($http) {
return {
siteOne: function() {
return $http({
method: "GET",
url: "siteURL/_api/web/lists/getByTitle('List 1')/items",
headers: {"Accept": "application/json; odata=verbose"}
});
},
siteTwo: function() {
return $http({
method: "GET",
url: "siteURL/_api/web/lists/getByTitle('List 2')/items",
headers: {"Accept": "application/json; odata=verbose"}
});
}
}
}]);
myApp.controller("myController", function($scope, $http, myFactory) {
myFactory.siteOne().success(function(data, status, headers, config) {
$scope.projects = data.d.results;
var items = $scope.projects,
totalItems = 0;
for (var i=0;i<items.length;i++) {
var currentItem = items[i];
if(currentItem.Status!="Completed") {
totalItems++;
}
};
$scope.oneItems = totalItems;
});
myFactory.siteTwo().success(function(data, status, headers, config) {
$scope.projects = data.d.results;
var items = $scope.projects,
totalItems = 0;
for (var i=0;i<items.length;i++) {
var currentItem = items[i];
if(currentItem.Status!="Completed") {
totalItems++;
}
};
$scope.twoItems = totalItems;
});
$scope.data = [
$scope.oneItems, $scope.twoItems
];
console.log(JSON.stringify($scope.oneItems));
console.log(JSON.stringify($scope.twoItems));
console.log(JSON.stringify($scope.data));
});
</script>
If I want to print each value separately, it shows the values! But if I try to put them inside the array, it shows the values as "null":
3
5
[null, null]
Why is this happening and how can I fix this? ..am I doing something wrong?
CODE UPDATE
Here is my code already working for those who'd like to see it. I changed the controller as Sergey Mell sugested, using $q, also I'm using AngularJS v1.7.5 (as georgeawg sugested):
myApp.controller("myController", function($scope, $http, myFactory, $q) {
$q.all([
myFactory.siteOne().then(response => {
var items = response.data.d.results,
totalItems = 0;
for (var i=0;i<items.length;i++) {
var currentItem = items[i];
if(currentItem.Status!="Completed") {
totalItems++;
}
};
$scope.oneItems = totalItems;
}),
myFactory.siteTwo().then(response => {
var items = response.data.d.results,
totalItems = 0;
for (var i=0;i<items.length;i++) {
var currentItem = items[i];
if(currentItem.Status!="Completed") {
totalItems++;
}
};
$scope.twoItems = totalItems;
})
]).then(function() {
$scope.data = [
$scope.oneItems, $scope.twoItems
];
console.log(JSON.stringify($scope.data));
});
});
You're putting your data before the requests have been finished. You have to wait till the end of both requests. I'd propose to use Promise.all or $q.all, which is more natural for AngularJS i.e.:
myApp.controller("myController", function($scope, $http, myFactory, $q) {
$q.all([
myFactory.siteOne().then(/* Your stuff here */),
myFactory.siteTwo().then(/* Your stuff here */),
]).then(function() {
$scope.data = [
$scope.oneItems, $scope.twoItems
];
})
Also assign values to key like:
$scope.data = [
dataItemOne: $scope.oneItems,
dataItemTwo: $scope.twoItems ];
You have best option as #Sergey Mell given below use $q service.
If you don't want to use $q.
then
Declare $scope.data = []; at top and use
$scope.data.push($scope.oneItems)
But make sure you have declared $scope.data to [] at the top otherwise it will throw error.
your controller code will be like
myApp.controller("myController", function($scope, $http, myFactory) {
$scope.data = [];
myFactory.siteOne().success(function(data, status, headers, config) {
$scope.projects = data.d.results;
var items = $scope.projects,
totalItems = 0;
for (var i=0;i<items.length;i++) {
var currentItem = items[i];
if(currentItem.Status!="Completed") {
totalItems++;
}
};
$scope.oneItems = totalItems;
$scope.data.push($scope.oneItems);
});
myFactory.siteTwo().success(function(data, status, headers, config) {
$scope.projects = data.d.results;
var items = $scope.projects,
totalItems = 0;
for (var i=0;i<items.length;i++) {
var currentItem = items[i];
if(currentItem.Status!="Completed") {
totalItems++;
}
};
$scope.twoItems = totalItems;
$scope.data.push($scope.twoItems );
});
/* $scope.data = [
$scope.oneItems, $scope.twoItems
];*/
console.log(JSON.stringify($scope.oneItems));
console.log(JSON.stringify($scope.twoItems));
console.log(JSON.stringify($scope.data));
});

$watch function is not getting triggered

I have a service which returns reponse. In response I have count of Users. I have a var userCount and I have a watch() on this userCount var.
var userCount=null;
var eventPromise = userSer.load(query, deviceType,$scope.duration);
eventPromise.then(function(response) {
console.log(response)
var dataLength = response.users.length;
$scope.numberOfRecords = dataLength;
if(dataLength > 0){
userCount = response.beaconCount;
setUserCount(userCount);
}
var setUserCount=function(data){
userCount=data;
};
var getUserCount=function(){
return userCount;
}
// This $watch function is not getting trigger as we are changing value of userCount from null to response.userCount.
$scope.$watch(userCount, function(newVal){
alert("M in watch func");
$scope.gridOptions.columnDefs[0].displayName = 'Beacon(' + getUserCount() + ')';
$scope.gridApi.core.notifyDataChange(uiGridConstants.dataChange.COLUMN);
})
You have messed up the usage of $scope.$watch, the correct usage of $scope.$watch is as below, refer docs here:
Usage1: watching changes of variable belongs to $scope.
$scope.userCount = null;
$scope.$watch("userCount", function() { ... });
Usage2: watching changes of variable not belongs to $scope.
var userCount = null;
$scope.$watch(function() { return userCount; }, function() { ... });
refer the below example.
angular.module("app", [])
.controller("myCtrl", function($scope, $timeout) {
$scope.data = null;
var data2 = null;
$scope.$watch("data", function() {
console.log("data change detected.");
});
$scope.$watch(function() { return data2; }, function() {
console.log("data2 change detected.");
});
$timeout(function() {
$scope.data = {id: 1};
data2 = {id: 2};
}, 2000);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
</div>
You cannot $watch any variable like this. Assign the userCount variable to $scope and it will work.
$scope.userCount = null;
userSer.load(query, deviceType, $scope.duration).then(function (response) {
console.log(response);
var dataLength = response.users.length;
$scope.numberOfRecords = dataLength;
if (dataLength > 0) {
$scope.userCount = response.beaconCount;
}
});

Javascript OOP private functions

I would like to create a constructor which can be instantiated with a json file which then is used by some private functions which in the end pass their results to a public function of the prototype. Is this the right approach?
Here more specific code:
//constructor
function queryArray(json){
this.json = json;
//init qry template with default values
function qryInit() {
var qryTemplate = {
//some stuff
}
return qryTemplate;
}
//generate array of request templates
function qryTempArray(json){
var template = qryInit();
var qryTempArray1 = [];
for(var i = 0; i < json.length; i++){
qryTempArray1.push({
'SearchIndex': json[i].SearchIndex,
'Title': json[i].Title,
'Keywords': json[i].Keywords,
'MinimumPrice': json[i].MinimumPrice,
'MaximumPrice': json[i].MaximumPrice,
'ResponseGroup': template.ResponseGroup,
'sort': template.sort
});
}
return qryTempArray1;
}
}
//function for finally building all the queries
queryArray.prototype.qryBuilder = function(){
var qryTempArray1 = [];
qryTempArray1 = qryTempArray(this.json);
//other stuff
}
If I call the qryBuilder function on an Object, I get an error
in the function qryTempArray at the json.length in the for loop (undefined).
Why that?
As the code is written above, I'm surprised you even get to the loop. It would seem you'd get undefined when you called qryBuilder();
I would expect something along the lines of the following to work.
//constructor
function queryArray(json) {
var self = this;
self.json = json;
//init qry template with default values
self.qryInit = function() {
var qryTemplate = {
//some stuff
}
return qryTemplate;
}
//generate array of request templates
self.qryTempArray = function(json) {
var template = self.qryInit();
var qryTempArray1 = [];
for (var i = 0; i < json.length; i++) {
qryTempArray1.push({
'SearchIndex': json[i].SearchIndex,
'Title': json[i].Title,
'Keywords': json[i].Keywords,
'MinimumPrice': json[i].MinimumPrice,
'MaximumPrice': json[i].MaximumPrice,
'ResponseGroup': template.ResponseGroup,
'sort': template.sort
});
}
return qryTempArray1;
}
return self;
}
queryArray.prototype.qryBuilder = function() {
var qryTempArray1 = [];
qryTempArray1 = this.qryTempArray(this.json);
return qryTempArray1;
}
var q = new queryArray([{
'SearchIndex': 0,
'Title': 'foo',
'Keywords': 'testing',
'MinimumPrice': 20,
'MaximumPrice': 40
}]);
console.log(q);
console.log(q.qryBuilder());

Sharing object array between controllers while working with modal window in angularJS

I am trying to work with an object array which I am sharing among two controllers one of which is dealing with modal window.
Here is the js code.
angular.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache', 'ui.bootstrap'])
.service('Faq', function ($http) {
this.faqList = [];
this.faqList = $http.get('/Json/faq.json');
this.getFaqs = function ()
{
return this.faqList;
}
this.addfaq = function (obj) {
this.faqList.push(obj);
};
})
.controller('AppCtrl', function ($scope,$modal,Faq) {
$scope.faqData = [];
Faq.getFaqs().then(function (msg) {
$scope.faqData = msg.data;
});
}
$scope.show = function () {
$modal.open({
templateUrl: "faqAddUpdate.html",
controller: "faqctrl"
});
};
})
.controller('faqctrl', function ($scope, $modalInstance, Faq) {
$scope.question = '';
$scope.id = '';
$scope.answer = '';
$scope.editFaq = function (id) {
$scope.divFaq = true;
$scope.faqs = [];
Faq.getData().then(function (msg) {
$scope.faqs = msg.data;
var l = $scope.faqs.length;
for (var i = 0; i < l; i++) {
if ($scope.faqs[i].id == id) {
$scope.question = $scope.faqs[i].question;
$scope.id = $scope.faqs[i].id;
$scope.answer = $scope.faqs[i].answer;
}
}
});
};
$scope.AddUpdateFAQ = function () {
var faq = {
id: $scope.id,
question: $scope.question,
answer: $scope.answer
};
Faq.addfaq(faq);
console.log(faq);
$modalInstance.close();
};
$scope.Cancel = function () {
$modalInstance.dismiss();
};
});
but when I am submitting the data through the modal it says this.faqList.push is not a function.
It is because your faqList variable is not an array.
You overide the first definition:
this.faqList = [];
With this:
this.faqList = $http.get('/Json/faq.json');
But $http.get returns a promise (see doc), not an array.
You should do something like this:
this.faqList = [];
$http.get('/Json/faq.json').then(function(result) {
// process your results here
this.faqList = result.data;
});
Not tried, but this is within the function scope, so create a _this var first might help:
this.faqList = [];
this.faqList = $http.get('/Json/faq.json');
var _this = this;
this.getFaqs = function ()
{
return _this.faqList;
}
this.addfaq = function (obj) {
_this.faqList.push(obj);
};

service is returning undefined in the array in angularjs

I am facing trouble with my angularjs script.
Background: I am trying to determine the location of the user, I have written my business logic in my service from where I am returning the location of the user.
Problem : The result I am getting in my console is as below :
[undefined] landingPage.js:11 undefined landingPage.js:11 undefined
var app = angular.module("PublicEvents", ["geolocation"]);
app.controller("iterator", ["$scope", "$http", "locationService1", function($scope, $http, locationService1){
$scope.targetCity = [];
$scope.targetCity.push(locationService1.location());
console.log($scope.targetCity);
$scope.$watch(function () { return locationService1.cityNameArray; },
function (value) {
$scope.targetCity = value;
console.log($scope.targerCity);
}
);
}]);
app.service("locationService1",['$http','$window', function( $http, $window){
var access = this;
this.location = function(){
$window.navigator.geolocation.getCurrentPosition(function(position) {
access.lat = position.coords.latitude;
access.long = position.coords.longitude;
access.locationData = [];
access.cityNameArray = [];
/*var url = "http://maps.googleapis.com/maps/api/geocode/json?latlng=18.9750,72.8258&sensor=true";*/
var url = "http://maps.googleapis.com/maps/api/geocode/json?latlng="+access.lat+","+access.long+"&sensor=true";
//AJAX CALL TO GET THE LOCATION
$http.get(url).then(function(response) {
access.locationData = response.data;
if(access.locationData.status == "OK" || access.locationData.status==200 ) {
angular.forEach(access.locationData.results, function(value, key){
var len = value.address_components.length;
for(var i = 0; i< len; i++){
if(value.address_components[i].types[0] =="locality" || value.address_components[i].types[0] =="sublocality_level_1"){
access.cityNameArray.push(value.address_components[i].long_name);
}
}
});
};
});
return access.cityNameArray;
});
};
}]);
Seems like you need to return data from an async call and you are returning value from outside the function. I'd suggest you to use promise pattern in such situation.
this.location = function(){
$window.navigator.geolocation.getCurrentPosition(function(position) {
access.lat = position.coords.latitude;
access.long = position.coords.longitude;
access.locationData = [];
access.cityNameArray = [];
/*var url = "http://maps.googleapis.com/maps/api/geocode/json?latlng=18.9750,72.8258&sensor=true";*/
var url = "http://maps.googleapis.com/maps/api/geocode/json?latlng="+access.lat+","+access.long+"&sensor=true";
//return promise from here..
return $http.get(url).then(function(response) {
access.locationData = response.data;
if(access.locationData.status == "OK" || access.locationData.status==200 ) {
angular.forEach(access.locationData.results, function(value, key){
var len = value.address_components.length;
for(var i = 0; i< len; i++){
if(value.address_components[i].types[0] =="locality" || value.address_components[i].types[0] =="sublocality_level_1"){
access.cityNameArray.push(value.address_components[i].long_name);
}
}
});
};
return access.cityNameArray; //returned from success callback
});
});
};
Inside controller you need to use .then function to get data from the service loacation function. You were doing console.log when you are doing async call which doesn't return anything.
locationService1.location().then(function(data){ //success callback.
$scope.targetCity.push(data)
},function(error){ //error callback.
console.log(error)
});

Categories

Resources