Angular ionic badge count not updating - javascript

I am new to angular and believe i am not fully understanding the digest cycle.
I am trying to update a badge count in a ion-tab.(using ionic)
"ion-tab"
<ion-tab title="Requests" badge="data.badge" ng-controller="RequestTabCtrl" badge-style="badge-assertive" icon-off="ion-pull-request" icon-on="ion-pull-request" href="#/tab/requests">
<ion-nav-view name="tab-requests"></ion-nav-view>
I have written a factory that will store and array. this array is updated through socket.io
"notifications factory"
.factory('notifications',function(){
var list = [];
return{
all: function(){
return list;
},
add: function(data){
list.push(data);
},
length: function(){
return list.length;
}
};
});
.controller('RequestTabCtrl',function($scope,notifications){
$scope.data = {
badge : notifications.length()
};
});
My problem is that the badge count is not updating when the notifications array is updated through socket.io. I have checked that the array is being updated. In fact i can console log the array length and can see it it changing. Also i have set a scope variable in the ion-tab's child io-nav-view and as a result can see the expression {{requests.length}} be updated in this view.
.controller('RequestsCtrl', function($scope,notifications) {
$scope.requests = notifications.all();
})
I have tried $watch(in RequestTabCtrl) on notifications.length. i have tried calling $apply(in RequestTabCtrl) which results in a $digest already in progress. I have tried $timeout and see no positive result (in RequestTabCtrl and the factory length function). Help will me much appreciated.

thanks to AjinderSingh, the solution was found.
So two ways to go about this. First using the $interval approach:
.controller('RequestTabCtrl',function($scope,notifications,$interval){
$interval(function(){
$scope.data = {
badge : notifications.length()
};
},2000);
});
Second approach is to $broadcast from the factory after an item has been added to the array. followed by catching this event in the controller:
.factory('notifications',function($rootScope){
var list = [];
return{
all: function(){
return list;
},
add: function(data){
list.push(data);
$rootScope.$broadcast('update');
},
length: function(){
return list.length;
}
};
});
.controller('RequestTabCtrl',function($scope,notifications,$interval){
$scope.$on('update',function(){
$scope.data = {
badge : notifications.length()
};
});
});
I am choosing the second approach as it seems to be cleaner.

$ionicPlatform.ready(function() {
$cordovaBadge.promptForPermission();
$scope.setBadge = function(value) {
$cordovaBadge.hasPermission().then(function(result) {
$cordovaBadge.set(value);
}, function(error) {
alert(error);
});
}
});
For complete reference plz check https://www.thepolyglotdeveloper.com/2015/07/modify-the-badge-number-of-an-ionic-framework-app/

Related

AngularJs variable scope outisde function

I am getting data using socket into angularJS controller.
$rootScope.list1= '';
socket.emit('ticker', symbol);
socket.on('quote', function(data) {
$rootScope.list1 = angular.fromJson(data.substring(3));
//I can't call any function from here to use this variable
});
I want to use updated list1 variable in my code below but I am not able to as it's value is coming as ''.
This can be because I am trying to access it in my script prior to it being updated i.e. prior to the response received.
Is there any way where I can use the updated value of variable list1 in my code below.
Edit 1
As suggested by #Manish Singh in one of the answers, I tried $rootScope.watch.It is reflecting new value for above peice of code but not for code given below.
$rootScope.peers = [];
industrysearch.searchindustry(indussymbol).then(function(results) {
industrysearch.searchpeers($scope.industrystock[0]._source.industry).then(function(results1) {
for (var number_stocks = 0; number_stocks < results1.length; number_stocks++) {
$rootScope.peers.push(results1[number_stocks]);
}
});
});
$rootScope.$watch('peers', function(newVal1, oldVal1) {
console.log(newVal1); //prints []
});
one is normal variable and one is used as array.I can;t see any other difference.
Edit 2
$watchCollection is use for arrays/collection which I missed.Below code is working.
$rootScope.$watchCollection('peers', function(newVal1, oldVal1) {
console.log(newVal1);
});
Thanks for help!
How about using a watch on $rootScope
$rootScope.$watch('list1', function(newVal, oldVal) {
//Do Something
)};
Try "$applyAsync":
$rootScope.list1= '';
socket.emit('ticker', symbol);
socket.on('quote', function(data) {
$rootScope.$applyAsync(function(){
$rootScope.list1 = angular.fromJson(data.substring(3));
});
});

How to show a loading message before filter with AngularJS?

I need to show some "Loading Message" when a filter is about to happen with AngularJS. My filter is fast, so I can't just show it before return the filtered data. My code:
.filter('filterName', function () {
return function (pacotes, escopo) {
var filtered = [];
pacotes.forEach(function (pacote) {
if (condition)
filtered.push(pacote);
});
return filtered;
}
})
What can I do to show some message, div, anything, before return this data?
Somewhere in your html:
<p id="loadingMessage" ng-show="showMessage"></p>
Filter:
.filter('filterName', function () {
$scope.showMessage = true;
$timeout(return function (pacotes, escopo) {
var filtered = [];
pacotes.forEach(function (pacote) {
if (condition)
filtered.push(pacote);
});
$scope.showMessage = false;
return filtered;
}, 3000);
})
I was not able to test this since I don't have all of your code. But something like this should work assuming I have the syntax right. You would have to inject $scope and $timeout in the appropriate places for this to work though.
Edit: I just realized escopo likely means scope in another language. Assuming that is true and you are actually passing in the scope, just put escopo where I have $scope.

How to react to change in data in a service in angularjs on a controller

I want to be able to share data between two controllers so that I can send a boolean to the service from the first controller which is turn triggers a change in the second controller.
Here is what the service looks like
exports.service = function(){
// sets Accordion variable to false ;
var property = true;
return {
getProperty: function () {
return property;
},
setProperty: function(value) {
property = value;
}
};
};
Now the first controller
exports.controller = function($scope, CarDetailsService, AccordionService ) {
$scope.saveDetails = function() {
AccordionService.setProperty(false);
}
}
and the second one
exports.controller = function($scope, AccordionService ) {
$scope.isCollapsed = AccordionService.getProperty();
}
The use case is that when i click on a button on the first controller,the service updates the data inside it, which is then served on the second controller, thus triggering a change in the second controller.
I have been looking around for quite some time but couldn't find a solution to this. Maybe im just stupid.
On the second controller you can $watch the variable you change in the first:
scope.$watch('variable', function(newValue, oldValue) {
//React to the change
});
Alternatively, you can use the $broadcast on the rootScope:
On the first controller:
$rootScope.$broadcast("NEW_EVENT", data);
On the other controller:
scope.$on("NEW_EVENT", function(event, data){
//use the data
});

AngularJS: Reassigning an object vs. replacing it in a controller

I am building a subscriber/observer pattern for displaying data in realtime for my angular app.
The observer is built with a factory injected into the angular controller and whose role is to fetch data and update it. The basic code structure can he found in this fiddle: http://jsfiddle.net/ctrager/67QR7/3/
var myApp = angular.module('myApp', [])
.factory('MyFactory', [function () {
var Collection = {};
Collection.isLoaded = 0;
Collection.data = [1, 2];
Collection.username = "corey and eric";
Collection.update = function () {
Collection.data.push(new Date())
}
Collection.replace = function () {
// If you do Collection.data = []
// here you are doing the same thing
// as the empty collection bug. I can't
// tell you EXACTLY why this confuses angular
// but I'm 99% sure it's the same phenomenon
Collection.data = [new Date()]
}
Collection.replace_fixed = function () {
// This works
Collection.data.length = 0
Collection.data.push(new Date())
}
return Collection;
}])
function MyCtrl($scope, MyFactory) {
$scope.name = 'Eric';
$scope.items = MyFactory.data;
$scope.replace = function(){
console.log("replace")
MyFactory.replace()
//$scope.items = MyFactor.data;
}
$scope.replace_fixed = function(){
console.log("replace_fixed")
MyFactory.replace_fixed()
//$scope.items = MyFactor.data;
}
$scope.update = function(){
console.log("update")
MyFactory.update()
}
}
The factory (MyFactory) contains a collection (Collection.data). Any push (/splice) to that collection is reflected in the scope, but if I replace the entire collection (Collection.replace()) the change is no longer reflected in $scope. Any idea why?
This works:
http://jsfiddle.net/67QR7/4/
changed the thing stored on scope to be the factory instead of data. then the html repeat to do items.data.
So it looks like this is because you replaced the reference inside collection, but that doesn't change where $scope.items was pointing to.
So you are creating a reference to MyFactory.data from $scope.items. Angular puts a $watch on $scope.items and looks for changes. When you call MyFactory.replace, you change MyFactory.data, but $scope.items remains the same. So as far as your watch is concerned, nothing has happened.
You can fix this by using replace_fixed, or watch for changes to MyFactory.data. http://jsfiddle.net/KtB93/
$scope.MyFactory = MyFactory;
$scope.$watch("MyFactory.data", function(newData) {
console.log('myFactory.data changed');
$scope.items = newData;
});
Or alternatively (probably better), you can use a function as the watch expression so you don't have to plop MyFactory on the scope (http://jsfiddle.net/XAW54/1/):
$scope.$watch(function() {
return MyFactory.data;
}, function(newData) {
$scope.items = newData;
});

AngularJS: $rootScope.$watch not working as expected

I'm trying to use the $rootScope to track favorites in my application, as they are modified I want to tell the application to update local storage to match.
In my controller I am using the following function to add / delete favorites:
$scope.toggleFavorite = function(product) {
var item = {
id: product.id,
name: product.name
}
if (_.findWhere($rootScope.favoriteDrinks, item)) {
console.log('Rootscope contains the item: Removing');
$rootScope.favoriteDrinks = _.reject($rootScope.favoriteDrinks, function(favorite) {
return favorite.id === item.id;
});
} else {
console.log('Rootscope doesn\'t contain the item: Adding');
$rootScope.favoriteDrinks.push(item);
}
console.log($rootScope.favoriteDrinks);
}
The console.log() produces expected results, it is updating and removing favorites as I add them throughout the application.
For the $rootScope I have the following code in my app.js`:
.run(['localStorageService', '$rootScope', function(localStorageService, $rootScope) {
if (!localStorageService.get('favoriteDrinks')) { localStorageService.add('favoriteDrinks', []) };
_.extend($rootScope, {
favoriteDrinks: localStorageService.get('favoriteDrinks')
});
$rootScope.$watch('favoriteDrinks', function() {
console.log('Favorite Drinks Modified');
});
}]);
So on application startup, if the localstorage keys don't exist, I create empty ones, then extend the $rootScope to contain the favorites as retrieved from localStorage. Then I add the $watch to the $rootScope, however it is only firing the console.log() when I remove something from the $rootScope, what am I doing wrong?
Hmm, I am not sure what _.reject(...) do, but I think it is asynchronous.
To make the $watch statement works properly, we need to put the update statement to an asynchronous call. In your case, you should you $apply or $timeout.
Just try:
$rootScope.$apply(function () {
$rootScope.favoriteDrinks.push(item);
});
or
$timeout(function () {
$rootScope.favoriteDrinks.push(item);
});
Using $timeout maybe hack-ish, but it can avoid $diggest already in process problem.
More info about $apply and $timeout.

Categories