$rootScope.$watchCollection is not working angularjs - javascript

I am trying to use $rootScope.$watchCollection in my code to update the data in controller B from controller A . but i am not getting any successful in it. as my application got stuck at this point ,so i am seeking your help so that i can came to know that where i am going wrong in code.
Controller B :-
app.controller('MenuCtrl', function($scope, LocalStorage, $stateParams,
$rootScope) {
$scope.user = {};
$scope.user.userName = LocalStorage.getData("userName");
$scope.user.profilePic = LocalStorage.getData("userProfile");
$rootScope.$watchCollection(function(n, o) {
if (n !== o) {
var list = $rootScope.wholecartList;
alert("Length " + list.length);
}
});
});
Controller A :-
app.controller('ProductCtrl', function($http, $scope, $ionicPopup, $state,
$ionicHistory, $ionicLoading, DataService, LocalStorage, $stateParams,
ProductId, DuplicateCheck, $rootScope) {
$scope.productList = DataService.getProducts();
$scope.getProductId = function(productId) {
ProductId.addProductId(productId);
$state.go("app.products-details");
}
var cartList = [];
$scope.cartListItems = function(product) {
if (cartList.length > 0) {
if (!DuplicateCheck.getProducts(product.product_id, cartList)) {
cartList.push(product);
}
} else {
cartList.push(product);
}
$rootScope.wholecartList = cartList;
}
});
Any help will be greatly appreciated
Thanks.

After this you need to update the $rootScope (say, run the apply cycle);
app.controller('ProductCtrl', function($http, $scope, $ionicPopup, $state,
$ionicHistory, $ionicLoading, DataService, LocalStorage, $stateParams,
ProductId, DuplicateCheck, $rootScope) {
$scope.productList = DataService.getProducts();
$scope.getProductId = function(productId) {
ProductId.addProductId(productId);
$state.go("app.products-details");
}
var cartList = [];
$scope.cartListItems = function(product) {
if (cartList.length > 0) {
if (!DuplicateCheck.getProducts(product.product_id, cartList)) {
cartList.push(product);
}
} else {
cartList.push(product);
}
$rootScope.wholecartList = cartList;
updateRootScope();
}
function updateRootScope(){
if(!$rootScope.$$phase){
$rootScope.$apply();
}
}
});

Related

Can't access $location in controller

I am trying to access $location in my controller and I am not having any luck. Below is my controller code.
bwApp.controller('bidding-controller', [
'$window', '$scope', '$rootScope', '$firebase', '$location',
'$compile', '$interval','$bwAppState', 'bidwrangler_api', 'AuctionService',
'CompanyService', 'NavigationService', 'UserService',
function($window, $scope, $rootScope, $firebase, $location, $compile, $interval,
$bwAppState, bidwrangler_api, AuctionService, CompanyService,
NavigationService, UserService) {
$scope.toggle_auction = function(item) {
if ($bwAppState.user.type == "clerk" && !item.listing) {
$window.location.href = "/clerk/" + item.auction.id + "?item=" + item.id;
}
else {
var restore_pos = null;
if ($location.search().section == 'itmes') {
restore_pos = $('.all-items').scrollTop();
$('.all-items').one('scroll', function(){$('.all-items').scrollTo(restore_pos)});
}
else if ($location.search().section == 'user_items'){
restore_pos = $('#your-items').scrollTop();
$('#your-items').one('scroll', function(){$('#your-items').scrollTo(restore_pos)});
}
NavigationService.update_push_state({item: item.id, section: 'auction'});
}
};
}
]);
When I am checking $location.search().section I keep getting an error in the console. If I am outside of $scope.toggleAuction() I have access to it. I have included/injected it correctly into the controller so I don't understand why I can't access it inside of the $scope function.
The error that I receive looks like the following:

Having difficulty injecting service into controller with AngularJS

I am having problems injecting ServicesData into SearchCtrl, and keep getting the following error message: Error: [$injector:unpr] Unknown provider: ServicesDataProvider <- ServicesData <- SearchCtrl. What could be the cause of this?
app.js
angular.module('starter', ['ionic', 'jett.ionic.filter.bar', 'starter.controllers'])
.state('app.playlists', {
url: '/playlists',
views: {
'menuContent': {
templateUrl: 'templates/playlists.html',
controller: 'SearchCtrl'
}
}
});
});
controller.js
angular.module('starter.controllers', [])
.controller('AppCtrl', function($scope, $ionicModal, $timeout) {
})
.controller('SearchCtrl', ["$scope", "ServicesData", function($scope, $timeout, ServicesData, $ionicFilterBar) {
// Get list items
function getItems () {
var items = [];
for (var x = 1; x < 3; x++) {
items.push({text: 'Item number ' + x});
}
$scope.items = items;
}
getItems();
// Ionic filter bar
var filterBarInstance;
$scope.visible = true;
$scope.nulledVisible = false;
$scope.toggle = function(event) {
if(event.target.id === 'nulled-search-button' && $scope.nulledVisible === false || event.target.id === 'header-search-button' && $scope.nulledVisible === false) {
$scope.visible = !$scope.visible;
$scope.nulledVisible = true;
}
};
$scope.showFilterBar = function () {
filterBarInstance = $ionicFilterBar.show({
items: $scope.items,
update: function (filteredItems, filterText) {
$scope.items = filteredItems;
if (filterText) {
console.log(filterText);
}
}
});
};
$scope.refreshItems = function () {
if (filterBarInstance) {
filterBarInstance();
filterBarInstance = null;
}
$timeout(function () {
getItems();
$scope.$broadcast('scroll.refreshComplete');
}, 1000);
};
}]);
services.js
angular.module('starter.services', [])
.service("ServicesData", [function () {
var servicesData = [
{
title: 'Car Repair and Maintenance',
total: 7,
id: 1
}
];
return {
getAllServices: function () {
return servicesData;
}
}])
2 things :
fix your controller declaration
["$scope", "ServicesData", function($scope, $timeout, $ionicFilterBar)
["$scope", "ServicesData", "$timeout", "$ionicFilterBar", function($scope, ServicesData, $timeout, $ionicFilterBar)
add dependency to your service module so your controller iwll be able to access what have been declared in your start.services module.
angular.module('starter.controllers', ['starter.services'])
Seems like you have an DI problem. Try to change this:
.controller('SearchCtrl', ["$scope", "ServicesData", function($scope, $timeout, ServicesData, $ionicFilterBar)
to:
.controller('SearchCtrl', ["$scope", "$timeout", "ServicesData", "$ionicFilterBar", function($scope, $timeout, ServicesData, $ionicFilterBar)
Rewrite dependency injection line.
.controller('SearchCtrl', ["$scope","$timeout","ServicesData", $ionicFilterBar, function($scope, $timeout, ServicesData, $ionicFilterBar)
the problem is sequence should be same and you have write dependency in both places.

Angular category sorting not working as per category names

I am trying to achieve category sorting in Angular js but its not working properly. It pulls data from desciption as well. I want to restrict it to categories names but no luck.
JS code:
var myApp = angular.module('myApp', []);
myApp.factory('Items', ['$http', function($http){
return {
get: function(callback){
$http.get('items.json').success(function(data){
callback(data);
})
}
}
}]);
myApp.factory('Categories', ['$http', function($http){
return {
get: function(callback){
$http.get('categories.json').success(function(data){
callback(data);
})
}
}
}]);
// Config and Routes
myApp.config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl:"home.html"
})
.when('/item/:id', {
templateUrl:"item.html"
})
})
myApp.controller('headerController', function($scope, $location) {
$scope.goHome = function () {
$location.path('/');
};
})
function Ctrl($scope) {
$scope.greeting = 'hello';
}
// Controllers
myApp.controller('ItemController', function($scope, $route, $location, $http, Items){
Items.get(function(response){
$scope.items = response;
});
// Update this value dynamically - onclick
$scope.filters = "food";
$scope.viewDetail = function(item) {
$location.path('/item/' + item.id);
}
})
myApp.controller('ListController', function($scope, $route, $location, $http, Categories){
$scope.sendCategory = function(category) {
// How can I pass this value to ItemController?
$scope.search =category.name;
};
$scope.orderProp='date';
$scope.tab = function (tabIndex) {
//Sort by date
if (tabIndex == 1){
//alert(tabIndex);
$scope.orderProp='date';
}
//Sort by views
if (tabIndex == 2){
$scope.orderProp = 'views';
}
};
$scope.sort = function(item) {
if ( $scope.orderProp == 'date') {
return new Date(item.date);
}
return item[$scope.orderProp];
}
})
myApp.controller('CategoryController', function($scope, $route, $location, $http, Categories){
Categories.get(function(response){
$scope.categories = response;
});
})
myApp.controller("tabsController", function ($scope) {
$scope.orderProp = 'date';
})
myApp.controller('ItemDetailController', function($scope, $route, $location, $http, Items){
Items.get(function(response){
$scope.items = response;
if ($route.current.params.id) {
angular.forEach($scope.items, function (v, k) {
if (v.id == $route.current.params.id) {
$scope.currItem = $scope.items[k];
return false;
}
});
}
});
})
can any one please help to find the way I can sort the data only as per my category names instead searching data on the overall pages?
Sharing the reference URL I found for this.
http://plnkr.co/edit/rh3wGYhuoHSHJEa4PoQi?p=preview
It would be great help if any can help me out.

Angular watch factory value

Say i have the following factory:
app.factory("categoryFactory", function (api, $http, $q) {
var selected = null;
var categoryList = [];
return {
getList: function () {
var d = $q.defer();
if(categoryList.length <= 0){
$http.get(api.getUrl('categoryStructure', null))
.success(function (response) {
categoryList = response;
d.resolve(categoryList);
});
}
else
{
d.resolve(categoryList)
}
return d.promise;
},
setSelected: function (category) {
selected = category;
},
getSelected: function () {
return selected;
}
}
});
now i have two controllers using this factory at the same time. Because of this both controllers has to be notified when updated for this i attempted the following:
app.controller('DashboardController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api','categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, categoryFactory) {
$scope.selectedCategory = categoryFactory.getSelected();
}]);
While my other controller looks like this:
app.controller('NavController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'FileUploader', 'categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, FileUploader, categoryFactory) {
$scope.categories = [];
categoryFactory.getList().then(function (response) {
$scope.categories = response;
});
$scope.selectCategory = function (category) {
categoryFactory.setSelected(category);
}
}]);
how ever when the NavController changed the value it was not changed in the DashboardController
My question is how can i either watch or in another way get notified when the value changes?
You can use an observer pattern, like so:
app.factory("categoryFactory", function (api, $http, $q) {
// the list of callbacks to call when something changes
var observerCallbacks = [];
// ...
function notifyObservers() {
angular.forEach(observerCallbacks, function(callback) {
callback();
});
}
return {
setSelected: function (category) {
selected = category;
// notify the observers after you change the value
notifyObservers();
},
registerObserver: function(callback) {
observerCallbacks.push(callback);
}
}
});
And then in your controllers:
app.controller('NavController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'FileUploader', 'categoryFactory', function ($http, $scope, $sessionStorage, $log, Session, api, FileUploader, categoryFactory) {
// ...
// init
(function() {
categoryFactory.registerObserver(function() {
categoryFactory.getList().then(function (response) {
$scope.categories = response;
});
});
})();
}]);
This way, any time setSelected is called, it calls each callback that you've registered in observerCallbacks. You can register these from any controller since factories are singletons and they will always be in the know.
Edit: just want to add that I may have put the notifyObservers() call in the wrong area (currently in setSelected) and that I may be putting the wrong update call in the controller (currently getList) but the architecture remains the same. In the registerObserver, put whatever you want to do when the values are updated and wherever you make changes that you want observers to know about call notifyObservers()
You could follow dot rule here so that prototypal inheritance will get followed.
Basically you need to have one object inside your service that will have selected variable, And will get rid of getSelected method.
Factory
app.factory("categoryFactory", function(api, $http, $q) {
var categoryFactory = {};
categoryFactory.getList = function() {
var d = $q.defer();
if (categoryList.length <= 0) {
$http.get(api.getUrl('categoryStructure', null))
.success(function(response) {
categoryList = response;
d.resolve(categoryList);
});
} else {
d.resolve(categoryList)
}
return d.promise;
}
categoryFactory.setSelected = function(category) {
categoryFactory.data.selected = category;
}
categoryFactory.data = {
selected: null
}
return categoryFactory;
});
Controller
app.controller('DashboardController', ['$http', '$scope', '$sessionStorage', '$log', 'Session', 'api', 'categoryFactory',
function($http, $scope, $sessionStorage, $log, Session, api, categoryFactory) {
//this will provide you binding without watcher
$scope.selection = categoryFactory.data;
}
]);
And then use {{selection.selected}} on html part will update a value when changes will occur in selection.

Angular service is undefined

I'm trying to call the mergeUserList() function that is inside my service. I do this is my controller that looks like this:
app.controller('UserManagementController', ['$http','$sessionStorage','api','$modal','$scope','Session', 'divisionService','$filter', function ($http, $sessionStorage, api, $modal, $scope, $state, Session, divisionService,$filter) {
divisionService.mergeUserList().then(function(response)
{
$scope.users = response;
});
}]);
And my service:
app.factory("divisionService", function (api, $http, $q) {
//Organization divisions with division users
var division = {};
var divisionArray = [];
var mergedUserList = [];
return {
mergeUserList: function () {
if (divisionArray == null || divisionArray.length == 0) {
var list = [];
var d = $q.defer();
this.getList().then(function () {
divisionArray.forEach(function (y) {
y.users.forEach(function (user) {
list.push(user);
});
d.resolve(list);
})
});
return d.promise;
}
else {
return null;
}
}
};
return division;
});
My problem is that when i run the code it says TypeError: undefined is not a function in line 1 in the controller. I know for a fact that the problem is not in the service, becuase I use it in another controller, and there it works.
You have one $state as a function argument which is not included in the array, change it to:
app.controller('UserManagementController', ['$http','$sessionStorage','api','$modal','$scope', '$state', 'Session', 'divisionService','$filter', function ($http, $sessionStorage, api, $modal, $scope, $state, Session, divisionService, $filter) {

Categories