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

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));
});

Related

$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;
}
});

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);
};

getting varriable from service to the controllers

im trying to get a varriable from this service but i can't manage to do this. i've looked online and got nothing.service:
.factory('localStorageService', function($rootScope){
$rootScope.go = function(task) {
var dataReceiver = localStorage.getItem('taskData');
var array = [];
var newArray = array.push({"title" : task});
if(dataReceiver === null) {
localStorage.setItem("taskData", JSON.stringify(array));
dataReceiver = JSON.parse(localStorage.getItem('taskData'));
console.log(dataReceiver);
}
else {
array = JSON.parse(dataReceiver);
var newArray2 = array.push({"title" : task});
localStorage.setItem("taskData", JSON.stringify(array));
dataReceiver = JSON.parse(localStorage.getItem('taskData'));
for(var i = 0; i < newArray2; i++) {
console.log(dataReceiver[i].title);
}
}
return dataReceiver;
}
})
controller:
.controller('PlaylistsCtrl', function($scope, PlaylistService, localStorageService) {
console.log(localStorageService.go());
})
it says it cannot read property go of undefined
You need to declare with module the factory belongs to, that's why localStorageService is undefined in your controller. And yes, you also shouldn't be appending go to rootScope. Your factory should look like this:
angular.module('myApp', []).factory('localStorageService', function($rootScope){
this.go = function(task) {
var dataReceiver = localStorage.getItem('taskData');
var array = [];
var newArray = array.push({"title" : task});
if(dataReceiver === null) {
localStorage.setItem("taskData", JSON.stringify(array));
dataReceiver = JSON.parse(localStorage.getItem('taskData'));
console.log(dataReceiver);
}
else {
array = JSON.parse(dataReceiver);
var newArray2 = array.push({"title" : task});
localStorage.setItem("taskData", JSON.stringify(array));
dataReceiver = JSON.parse(localStorage.getItem('taskData'));
for(var i = 0; i < newArray2; i++) {
console.log(dataReceiver[i].title);
}
}
return dataReceiver;
};
return this;
});
By returning the factory object it and all of it's methods are then available when injected into your controller.
Your problem is that you put the method 'go' on the rootscope and not on the factory.
Your factory is returning the object dataReceiver which does not have a method 'go'.
Put the 'go' method on the object that is being returned from the factory and you will be able to get it.
Here is a basic plunkr: http://plnkr.co/edit/wbCedJx8BJ4nOvuNWQc7
JavaScript:
var app = angular.module('app', []);
app.controller('appCtrl', function ($scope, myFactory) {
$scope.greetings = myFactory.go();
});
app.factory('myFactory', function () {
this.go = function () {
return 'hello from factory';
};
return this;
});
Markup:
<html ng-app="app">
<head>
<script data-require="angular.js#*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="appCtrl">
<h1>Greetings: {{ greetings }}</h1>
</body>
</html>
Hope this helps.
Service
app.factory('localStorageService', ['$rootScope', function($rootScope) {
return {
go: function() {
//do your stuff here
var dataReceiver = localStorage.getItem('taskData');
var array = [];
var newArray = array.push({"title" : task});
if(dataReceiver === null) {
localStorage.setItem("taskData", JSON.stringify(array));
dataReceiver = JSON.parse(localStorage.getItem('taskData'));
console.log(dataReceiver);
}
else {
array = JSON.parse(dataReceiver);
var newArray2 = array.push({"title" : task});
localStorage.setItem("taskData", JSON.stringify(array));
dataReceiver = JSON.parse(localStorage.getItem('taskData'));
for(var i = 0; i < newArray2; i++) {
console.log(dataReceiver[i].title);
}
}
return dataReceiver;
}
}
}]);
controller
app.controller('PlaylistsCtrl',
function PlaylistsCtrl($scope, PlaylistService, localStorageService) {
console.log(localStorageService.go())
}
)

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

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;
});
})

AngularJS Service Isn't Returning Data

I have to AngularJS services to load data to my app which are set up in essentially the same way, although one works and one does not.
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives'])
.service('uniqueLists', function ($http) {
console.log("Getting Unique Lists")
var itemsToList = [
'designer',
'store',
'category'
]
var uniqueLists = {};
var promise = (function(){
console.log("Inside Function")
for (var i = 0; i<itemsToList.length; i++){
var item = itemsToList[i];
uniqueLists[item] = [];
$http.get('/api/uniques/' + item, { cache: true}).
success(function (data){
uniqueLists[item] = data.query;
console.log(i + " out of " + itemsToList.length);
if (i == itemsToList.length -1){
return uniqueLists;
}
});
};
})();
return promise;
})
I think my main issue is that the $http call is non-blocking. For instance, when I try to console.log(i + " out of " + itemsToList.length) I see:
3 out of 3
3 out of 3
3 out of 3
In turn, in my app when I try to use uniqueLists like so:
function homeCtrl($scope, $location, uniqueLists, userInfo){
uniqueLists.then(function(obj){
// Do stuff
});
}
I get the error TypeError: Object [object Object] has no method 'then'
Any ideas on how to fix this? The $http.get api call works just fine so I think it's just a blocking/async problem.
Try this untested code
angular.module('myApp', [])
.service('uniqueLists', function ($http, $q) {
console.log("Getting Unique Lists")
var itemsToList = [
'designer',
'store',
'category']
var uniqueLists = {};
var promises = []
console.log("Inside Function")
for (var i = 0; i < itemsToList.length; i++) {
var item = itemsToList[i];
promises.push(http.get('/api/uniques/' + item, {
cache: true
}));
};
var defered = $q.defer();
$q.all(promises).then(function (data) {
for (var i = 0; i < data.length; i++) {
var item = itemsToList[i];
uniqueLists[item] = data[i].query;
}
defered.resolve(uniqueLists);
}, function (error) {
defered.reject(error)
});
return defered.promise;
})

Categories

Resources