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

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.

Related

How to inject a custom filter in AngularJS 1.6

I have a component into which I would like to inject a custom filter, status.
My component looks like this:
function ClaimsListController(dpClaimsListService) {
var ctrl = this;
ctrl.claims = null;
ctrl.searchCriterion = null;
ctrl.loadClaimsList = function() {
dpClaimsListService.getUploadRequests(1,
function (claims) {
ctrl.claims = claims.data;
},
function () {
// error handling? display message to user?
});
}
ctrl.loadClaimsList(1);
}
angular.module('dpApp').component('dpClaimsListService', {
templateUrl: '/templates/dp-claims-list.tmpl.html',
controller: ClaimsListController
});
I can't work out how to inject my status filter into my component in a DI-minificaiton safe way. Any help appreciated.
Turns out that I don't need to inject the filter; I neglected to include it in my bundle.

How to check if all documents are loaded with Firebase.util pagination

How can I check if I have to stop calling the loadMore() function, because all the documents have already been loaded from the database?
In the example below I'm using Ionic, but it's the same also with ng-infinite-scroll in AngularJS apps.
This is my actual code:
HTML:
...
<ion-infinite-scroll
ng-if="!noMoreItemsToLoad"
on-infinite="loadMore()"
distance="5%">
</ion-infinite-scroll>
</ion-content>
JS Controller:
$scope.loadMore = function(){
console.log('Loading more docs...');
Items.loadMore(); // calling the .next() method inside the Items service
if( !Items.hasNext()) { $scope.noMoreItemsToLoad = true; }
$scope.$broadcast('scroll.infiniteScrollComplete');
}
JS Items Factory:
.factory('Items', function (FIREBASE_URL, $firebaseArray, $firebaseObject) {
var itemsRef = new Firebase(FIREBASE_URL + 'items/');
var scrollRef = new Firebase.util.Scroll(itemsRef, 'name');
var self = {
getAllItems : function(){ ... },
loadMore: function(){
scrollRef.scroll.next(4);
},
hasNext: function(){
if(scrollRef.scroll.hasNext()) { return true; }
else { return false; }
}
}
return self;
}
Do the scroll.next in timeout, for example:
loadMore: function(){
$timeout(function() {
scrollRef.scroll.next(4);
});
},
I had the same issue and I think the solution is to modify the hasNext() function on firebase.util.js:
Cache.prototype.hasNext = function() {
return this.count === -1 || this.endCount >= this.start + this.count;
};
I put a missing equal sign (=) before this.start
I hope it works for you.

How to make an AngularJS scope variable dependent on media query with EnquireJS?

The goal is to make an Angular scope variable dependent on the screen resolution. I found that the EnquireJS library does just that. The final working result should be that the menu collapses when screen is 480px, based on an isCollapsed variable. (I'm using Angular-ui from bootstrap) Note: I must use Angular.
I can attach the Angular scope variable (isCollapsed) to the Javascript $window and address the $window in EnquireJS, this is what I have.
Create module + controller and attach scope + window
angular.module('PremiumMeat', ['ui.bootstrap']);
angular.module('PremiumMeat').controller('CollapseCtrl', function ($scope, $window) {
$scope.isCollapsed = false;
$window.collapsed = false;
});
Enquire setup, initialize variable on false
// Enquire configuration
var enquireQuery= "screen and (max-width:480px)";
var enquireQueryHandler = {
setup: function () {
$scope.isCollapsed = false;
$window.collapsed = false;
angular.element(document.querySelector('[ng-controller="CollapseCtrl"]')).scope().isCollapsed=false;
},
The isCollapsed variable should be initialized on false and become true when screen size reaches 480px;
I'm trying to address the variable through the $window and both the document object, but none work.
match: function () {
$scope.isCollapsed = true;
$window.collapsed = true;
angular.element(document.querySelector('[ng-controller="CollapseCtrl"]')).scope().isCollapsed=true;
},
unmatch: function () {
$scope.isCollapsed = false;
$window.collapsed = false;
angular.element(document.querySelector('[ng-controller="CollapseCtrl"]')).scope().isCollapsed=false;
}
};
Now the question is where to initialize the enquireJS to make it all work.
enquire.register(enquireQuery, enquireQueryHandler, true);
When I put it in the controller it stops working and outside it, it doesn't overrule.
Final working result should be that the menu collapses when screen is 480px. Note: I must use Angular (angular-ui bootstrap)
I created a service to handle EnquireJS media queries in my Angular application that might be of use to you: https://gist.github.com/schuyberg/034a9982bf8326c19fc9
For your case here, the service would look something like this:
services.factory('max480', ['$rootScope', '$timeout', function ($rootScope, $timeout) {
var max480 = {
watch: function() { enquire.register('screen and (max-width: 480px)', max480handler); },
unwatch: function() { enquire.unregister('screen and (max-width: 480px)'); },
ismatch: function(callback) { $rootScope.$on('match480', callback); },
notmatch: function(callback) { $rootScope.$on('unmatch480', callback); },
};
var max480handler = {
match: function() {
$timeout(function(){
$rootScope.$emit('match480');
});
},
unmatch: function(){
$rootScope.$emit('unmatch480');
}
};
return max480;
}]);
Then, inject the service in your controller, and use the following to register the enquire listener, and act on changes:
// this setup can live in your controller
$scope.isCollapsed = false;
$window.collapsed = false;
angular.element(document.querySelector('[ng controller="CollapseCtrl"]')).scope().isCollapsed=false;
// use the service to listen for, and react to changes
max480.watch();
max480.ismatch(function(){
$scope.isCollapsed = true;
$window.collapsed = true;
angular.element(document.querySelector('[ng-controller="CollapseCtrl"]')).scope().isCollapsed=true;
});
max480.notmatch(function(){
$scope.isCollapsed = false;
$window.collapsed = false;
angular.element(document.querySelector('[ng-controller="CollapseCtrl"]')).scope().isCollapsed=false;
});
This service has the advantage of being reusable throughout your application. You can also use max480.unwatch(); to unregister the listener if you need to.

Make switch directive

I'm trying to pass in a $scope that I want to change the value on.
These are two switch button on the same page that.
View
<div class="input">
<switch state="false" toggle="user.emailNotification">
<flip></flip>
</switch>
</div>
<div ng-click="saveNotifySettings()" class="button fill primary">Vista</div>
Controller
app.controller('notifySettingCtrl', function($scope, Users){
Users.get().$promise.then(function(data) {
$scope.user = data;
console.log($scope.user.emailNotification);
});
$scope.saveNotifySettings = function() {
console.log("PUT the new value for the switch");
};
});
When I press the button the state changes from false to true
First I want to init the state with the existing value from $scope.user.emailNotification and then change it and pass the changes to the controller.
The beginning of the my directive.
switch directive
(function() {
define(['angular', 'app', 'underscore'], function(angular, app, _) {
app.directive('switch', function() {
return {
restrict: 'E',
scope: {
value: '&toggle',
},
link: function(scope, element) {
var x = scope.value();
element.bind('mouseenter', function() {
console.log(x);
});
var $element = angular.element(element),
uniqueId = _.uniqueId('switch-'),
state = $element.attr('state');
state = typeof state === 'undefined' ? false : state;
$element.data('uniqueId',uniqueId)
.attr('state',state)
.attr('alive',true);
$element.on('click.'+uniqueId,function(){
if (state === true) {
$(this).attr('state',false);
state = false;
} else {
$(this).attr('state',true);
state = true;
}
});
}
};
});
});
}).call(this);
I'm very new at creating directives, so any help is well appreciated.
I have spend way to much time at this and it getting frustrating :/
Update:
I have created http://jsfiddle.net/HuLn4/. I have taken the pointers from you and refactored.
TLDR: I'm trying to create directive by sending in the model that I want to change in this case user.emailNotification and when the element is clicked on it changes the value from true/false and false/true and stores it back to the controllers $scope.user so it can be PUT to server and the state attribute is only to tell the look on the switch and for the initialize on the button ( on / off ).

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