Create directive to check new message and add badge - javascript

I use this controller in ionic app to check new message or activity and add a badge if is there news:
.controller('checkNew', function($scope, getNewMsg, getNewAct, $localstorage, $cordovaLocalNotification, $http, $state) {
getNewMsg.getNew(function(data) {if(data!=0){$scope.addActivity(data);$scope.counterAct = data}else{$scope.cancelAllNotification}});
getNewAct.getNew(function(data) {if(data!=0){$scope.addNotification(data);$scope.counter = data}else{$scope.cancelAllNotification}});
and this is for example my .factory getNewMsg:
.factory('getNewMsg', function($http, $localstorage, $timeout){
return {
getNew: function(callback){
var user_id = $localstorage.get('user_id');
var timer;
function myLoop(){
timer = $timeout(function(){console.log( "Timeout executed")},5000);
timer.then(
function(){$http.post('http://www.digitalxp.it/appwork/include/check_msg.asp?id='+user_id).success(function(data){callback(data)}).error(function(){alert("Errore di comunicazione!")});myLoop()},
function() {console.log("Timer rejected!")}
);
}
myLoop();
}}
})
my problem is that I've to call the controller each time to add the badge in the header, but I would check only one time and view the badge on all ion-view of the app! (also the side menu near message item!)
I think is it possible with directive, but I dont know how to start!

I've updated this to use broadcas as you've requested, now your controller will be registered to the event newMessageReceived and will update every 5 seconds. Also, this acts more as a service, so I've updated the module to be a service and not a factory.
Please note that I changed timer.then(setNew, handleError); to timer.then(setNew(), handleError);
.controller('checkNew', function($scope, messageService, getNewAct, $localstorage, $cordovaLocalNotification, $http, $state) {
//register to broadcast and update when the messages are updated
messageService.newMessageReceived($scope, updateMessage)
function updateMessage(message) {
if(message){
$scope.addActivity(message);
$scope.counterAct = message;
} else {
$scope.cancelAllNotification
}
}
});
.service('messageService', function($rootScope, $http, $localstorage, $timeout){
/* Initialization */
//setup timer to run every 5 seconds
var timer = $timeout(timeoutFunction, 5000);
//set the actions for resolve and reject
timer.then(setNew(), handleError);
function timeoutFunction() {
return;
}
function handleError() {
console.log('Timer rejected');
}
//every time the newMessageRecieved event is broadcasted, run the callback and register the scope
function newMessageReceived(scope, callback) {
callback(getNew());
scope.$on('newMessageReceived', function() {
callback(getNew());
});
}
function getNew() {
return $localstorage && $localstorage.message || undefined;
}
function setNew() {
var user_id = $localstorage.get('user_id');
return $http.post('http://www.digitalxp.it/appwork/include/check_msg.asp?id='+user_id)
.success(function(data){
$localStorage.message = data;
$rootScope.$broadcast('newMessageReceived');
})
.error(function(){alert("Errore di comunicazione!")})
}
return {
newMessageReceived: newMessageReceived
};
});

Related

Angularjs watch on Service Variable from directive best Practice

i'm trying to display a Bootstrap modal Dialog when a Variable in a Service is changed.
I'm currently doing this with broadcast. I'm new to angular so any help to improve my code is appreciated.
This Code works but i wanted to know if this is the correct way to do this.
My Service:
utils.service('UtilsService', function ($rootScope) {
this.objectToDelete = "";
this.deleteMessage = "";
this.DeleteObject = function (object, message) {
this.objectToDelete = object;
this.deleteMessage = message;
$rootScope.$broadcast('objectChanged', this.objectToDelete);
}
});
My Directive:
verwaltungApp.directive('deletedialog', ['UtilsService', function (UtilsService) {
return {
restrict: 'E',
controller: function ($scope, $attrs, UtilsService) {
$scope.$on("objectChanged", function (event, args) {
if (UtilsService.objectToDelete) {
$scope.ObjectToDelete = UtilsService.objectToDelete;
$scope.Message = UtilsService.deleteMessage;
$('#modalErrorDialog').modal('show');
}
});
$scope.DeleteObject = function () {
$scope.ObjectToDelete.Delete();
$scope.ObjectToDelete = null;
$('#modalErrorDialog').modal('hide');
}
$scope.Cancel = function () {
$scope.ObjectToDelete = null;
$('#modalErrorDialog').modal('hide');
}
},
templateUrl: '/shared/DeleteDialog'
};
}]);
I tried it with $watch before but that did not work for me.
The main thing i want to do is to place this directive on my Layout Page so i can call it from any controller with an object i want to delete.

HttpInterceptor request broadcast not running whilethe response broadcast does run

Hi I am trying to create a laoding box in my angular application here is what I have so far:
This is the loadingBox directive:
app.directive('loadingBoxDir', function (eventsSvc) {
var loadingBoxDir = {
templateUrl: '/Scripts/App/Infrastructure/Directives/loadingBoxView.html',
restrict: "E",
scope: {
isLoadingBoxVisible: '='
}
};
loadingBoxDir.link = function ($scope, $element) {
var loadingBox = $element.find('.fa-spinner');
var body = angular.element('body');
var loadingBoxParent = $element.find('#global-spinner');
loadingBox.css({
"position": "absolute",
"top": body.height() / 2 - loadingBox.height() / 2 + "px",
"left": body.width() / 2 - loadingBox.width() / 2 + "px"
});
$scope.$on(eventsSvc.global.loadingBoxShow, function () {
loadingBoxParent.addClass('global-spinner-visible');
});
$scope.$on(eventsSvc.global.loadingBoxHide, function() {
loadingBoxParent.removeClass('global-spinner-visible');
});
}
return loadingBoxDir;
});
And this is my interceptor:
app.provider('httpInterceptorSvc', [function () {
this.$get = function ($q, $rootScope, $injector, eventsSvc) {
var httpInterceptorSvc = {};
httpInterceptorSvc.request = function (requestParam) {
$rootScope.$broadcast(eventsSvc.global.loadingBoxShow);
return requestParam;
}
httpInterceptorSvc.response = function (responseParam) {
hideLoadingBox();
return responseParam;
}
httpInterceptorSvc.requestError = function (requestErrorParam) {
hideLoadingBox();
return $q.reject(requestErrorParam);
}
httpInterceptorSvc.responseError = function (responseErrorParam) {
hideLoadingBox();
return $q.reject(responseErrorParam);
}
function hideLoadingBox() {
var $http = $injector.get('$http');
if ($http.pendingRequests.length === 0) {
$rootScope.$broadcast(eventsSvc.global.loadingBoxHide);
}
}
return httpInterceptorSvc;
}
}])
This is the events service:
app.factory('eventsSvc', [function () {
var eventsSvc = {
global: {
loadingBoxHide: 'global.loadingBox.hide',
loadingBoxShow: 'global.loadingBox.show'
}
};
return eventsSvc;
}])
Now as you can see in the interceptor in both the request and response I am trying to broadcast to the loadingBoxDir. The problem is that the request broadcast does not reach the directive.
One interesting fact is that the response broadcast reaches the directive and I cannot figure out what is the difference between the two
Can anyone tell me what I am doing wrong?
I figured out the problem with the code.The ideea is that ajax calls get executed as soon as the page loads, but the directives did not have time to be initialized that's why when broadcast gets called it does not reach this on function:
$scope.$on(eventsSvc.global.loadingBoxShow, function () {
loadingBoxParent.addClass('global-spinner-visible');
});
In order to solve the problem I added this piece of code:
loadingBoxParent.addClass('global-spinner-visible');
What this does is sets the loading box visible as soon as the page loads which makes sense because I am executing ajax calls in the controller.

$on event, set a variable to true

This is a dumb scoping issue and I'm bad at Javascript. Pretty sure I don't know how to return the value of a variable up to parent scope (e.g. look for the **** in AppCtrl)
I have 2 controllers. AppCtrl (parent) and MainCtrl (child)
<div ng-controller="AppCtrl">
<div ng-controller="MainCtrl">
</div>
</div>
I am fetching some random JSON data in the MainCtrl.
.controller('MainCtrl', function ($scope, $http) {
$scope.datas = [];
$http.jsonp('http://filltext.com/?rows=10&delay=1&fname={firstName}&callback=JSON_CALLBACK').
success(function(data){
$scope.datas[0] = data;
console.log($scope.datas);
$scope.$emit('load::1');
});
$http.jsonp('http://filltext.com/?rows=10&delay=2&fname={firstName}&callback=JSON_CALLBACK').
success(function(data){
$scope.datas[1] = data;
console.log($scope.datas);
$scope.$emit('load::2');
});
$http.jsonp('http://filltext.com/?rows=10&delay=4&fname={firstName}&callback=JSON_CALLBACK').
success(function(data){
$scope.datas[2] = data;
console.log($scope.datas);
$scope.$emit('load::3');
});
});
When that data is successful I will emit a message to AppCtrl.
On the AppCtrl I am listening for the emitted messages and setting the array var load = true.
.controller('AppCtrl', function ($scope, $http) {
//*****
var load = [];
$scope.$on('load::1', function(){
//how do i return this value to the var above?
load[0] = true;
});
$scope.$on('load::2', function(){
load[1] = true;
});
$scope.$on('load::3', function(){
load[2] = true;
});
if(load[0]=== true && load[1] === true && load[2] == true) {
console.log('loaded');
}
});
when all three are set to true I would like the console.log to log out 'loaded'.
If condition will run only once so you can call if condition with every $on listener or combine multiple listener and check if all content is loaded or not.both ways are same.
myapp.controller('AppCtrl', function ($scope, $http) {
//*****
var load = [];
angular.forEach(['load::1', 'load::2', 'load::3'], function (value) {
$scope.$on(value, function (event) {
load.push(true);
if (load[0] === true && load[1] === true && load[2] == true) {
alert('loaded');
}
});
});
});
Fiddle Demo
It will never print 'loaded' because this statement run only once
if(load[0]=== true && load[1] === true && load[2] == true) {
console.log('loaded');
}
2. To share data between controllers in Angular is better to use services https://docs.angularjs.org/guide/services.

How update main controller $scope since a song controller in Angularjs

i am working with angular and Parse.com and I have a problem:
I have a "mainController" that its in all the html document and a routeProvider with some pages and controllers.
function mainController($scope)
{
$scope.logeado = (Parse.User.current()!=null)
if (Parse.User.current()==null)
{
$scope.showuser=""
}
else
{
$scope.showuser=Parse.User.current().get('username')
}
$scope.logout = function()
{
Parse.User.logOut();
$scope.logeado = (Parse.User.current()!=null);
$scope.$apply();
}
};
One of this controller is "loginController". In this controller make the login, but my problem is:
If i logout, the function is in the maincontroller and this ng-show="logeado" change because the variable is inside, but if i login since logincontroller, i can change "Parse.User.current()" but $scope.logeado isn't update, and i need update all the page to see the changes.
How can i do to update de variable?
One of the way to solve problem is to implement pattern observer. Let
Parse.User.current notify about his state.
function mainController($scope){
Parse.User.current.onChange(function () {
$scope.logeado = (Parse.User.current()!=null);
if (Parse.User.current() == null) {
$scope.showuser=""
} else {
$scope.showuser=Parse.User.current().get('username')
}
});
$scope.logout = function() {
Parse.User.logOut();
};
};
Finally, I have make a function in mainController($scope):
$scope.login2= function(){
$scope.logeado = (Parse.User.current()!=null);
if (Parse.User.current() == null)
{
$scope.showuser=""
}
else
{
$scope.showuser=Parse.User.current().get('username')
}
};
and call it since loginController($scope) because $scope.login2 is inherited in this.

Broadcasting functions through a service trigger the function multiple times instead of one

I created a service that shares a confirm modal method, and allow to broadcast methods between controillers.
services.SharedService = function($rootScope, $modal) {
var sharedService = {
controller : '',
method : '',
args : []
};
sharedService.prepare = function(controller, method){
this.controller = controller;
this.method = method;
this.broadCast();
};
sharedService.broadCast = function(){
$rootScope.$broadcast('menuBroadcast');
};
return sharedService;
});
Then I have three controllers :
controllers.ctrl1 = function($scope, $rootScope, SharedService) {
$rootScope.$on('menuBroadcast', function() {
if (SharedService.controller == 'ctrl1') {
$scope[SharedService.method]();
}
});
$scope.delete = function(){
var c = window.confirm("Are you sure you want to delete it?");
if(c === true){
//delete
}
};
};
and
controllers.ctrl2 = function($scope, $rootScope, SharedService) {
$rootScope.$on('menuBroadcast', function() {
if (SharedService.controller == 'ctrl1') {
$scope[SharedService.method]();
}
});
$scope.delete = function(){
var c = window.confirm("Are you sure you want to delete it?");
if(c === true){
//delete
}
};
};
};
controllers.menu = function($scope, SharedService) {
$scope.delete1 = function() {
console.debug("Calling delete 1");
SharedService.prepare('ctrl1', 'delete');
};
$scope.delete2 = function() {
console.debug("Calling delete 2");
SharedService.prepare('ctrl2', 'delete');
};
}
The first time I open the confirm from ctrl1, clicking on the ok button works as expected. I can open this modal as many times, it will work.
Then, switching to ctrl2, I open the confirm , I have to click two times on the ok button to be able to close the confirm box.
The console debugs shows that the "calling delete1" and "calling delete2" are triggered only once. But the console.debug from on("menuBroadcast") is triggered sometimes up to 3 times. Any idea why the service triggers the event more than one time? When injected, is it instantiated more than once?
Duplicate of
How can I unregister a broadcast event to rootscope in AngularJS?
The controller is instantiated more than once . I have to un-register the $rootScope.$on listener on when the $destroy is invoked.
var cleanUpFunc = $rootScope.$on('menuBroadcast', function {
if (SharedService.controller == 'ctrl1') {
$scope[SharedService.method]();
}
});
$scope.$on('$destroy', function() {
cleanUpFunc();
});

Categories