$watch function is not getting triggered - javascript

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

Related

How do I test my Angular scope functions in karma + jasmine?

I'm fairly new to Angular and very new to Jasmine testing. I have a function in my controller at pushes an object into an empty array (object taken from json data).
my controller with the functions pertaining to the cart:
$scope.cart = [];
$scope.addItemToCart = function(choc) {
var cartItem = readCartItem(choc.id);
if(cartItem == null) {
//if item doesn't exist, add to cart array
$scope.cart.push({type: choc.type, id: choc.id, price: choc.price, quantity: 1})
} else {
//increase quantity
cartItem.quantity++;
}
}
$scope.cartTotal = function() {
var sum = 0;
$scope.cart.forEach(function(item) {
sum += item.price * item.quantity;
});
return sum;
}
$scope.getTotalQuantity = function() {
var totalItems = 0;
$scope.cart.forEach(function(item) {
totalItems += item.quantity;
});
return totalItems;
}
$scope.clearCart = function() {
$scope.cart.length = 0;
}
$scope.removeItem = function(choc) {
$scope.cart.splice(choc,1);
}
function readCartItem(id) {
//iterate thru cart and read ID
for(var i=0; i<$scope.cart.length; i++) {
if($scope.cart[i].id === id) {
return $scope.cart[i]
}
}
return null;
}
My test:
describe('Controller: ChocoListCtrl', function () {
beforeEach(module('App'));
var scope, ctrl, json;
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
// ChocoListCtrl = $controller('ChocoListCtrl', {});
ctrl = $controller("ChocoListCtrl", { $scope:scope })
}));
it('should be defined', function (){
expect(ctrl).toBeDefined();
});
it('should have an empty cart', function(){
expect(scope.cart.length).toBeLessThan(1);
});
describe('cart functions', function(){
beforeEach(function(){
scope.addItemToCart();
})
it('should add objects into the cart', function(){
expect(scope.cart.length).toBeGreaterThan(0);
})
});
The error I come back with when running the test:
TypeError: undefined is not an object (evaluating 'choc.id')
I thought I was pushing an object into the array? Am I missing something? Should I include the JSON file if it helps?
Any guidance would help. Thank you!
You're not passing in a parameter to $scope.addItemToCart. So when it tries to read choc it can't because it's undefined.
This line is causing the error:
beforeEach(function(){
scope.addItemToCart(); // No parameter being passed in
})

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

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

Categories

Resources