-
-
Save katowulf/7328023 to your computer and use it in GitHub Desktop.
/** | |
* This module monitors angularFire's authentication and performs actions based on authentication state. | |
* | |
* See usage examples here: https://gist.github.com/katowulf/7328023 | |
*/ | |
angular.module('waitForAuth', []) | |
/** | |
* A service that returns a promise object, which is resolved once $firebaseAuth | |
* is initialized (i.e. it returns login, logout, or error) | |
*/ | |
.service('waitForAuth', function($rootScope, $q, $timeout) { | |
var def = $q.defer(), subs = []; | |
subs.push($rootScope.$on('$firebaseAuth:login', fn)); | |
subs.push($rootScope.$on('$firebaseAuth:logout', fn)); | |
subs.push($rootScope.$on('$firebaseAuth:error', fn)); | |
function fn(err) { | |
if( $rootScope.auth ) { | |
$rootScope.auth.error = err instanceof Error? err.toString() : null; | |
} | |
for(var i=0; i < subs.length; i++) { subs[i](); } | |
$timeout(function() { | |
// force $scope.$apply to be re-run after login resolves | |
def.resolve(); | |
}); | |
} | |
return def.promise; | |
}) | |
/** | |
* A directive that hides the element from view until waitForAuth resolves | |
*/ | |
.directive('ngCloakAuth', function(waitForAuth) { | |
return { | |
restrict: 'A', | |
compile: function(el) { | |
el.addClass('hide'); | |
waitForAuth.then(function() { | |
el.removeClass('hide'); | |
}) | |
} | |
} | |
}) | |
/** | |
* A directive that shows elements only when the given authentication state is in effect | |
*/ | |
.directive('ngShowAuth', function($rootScope) { | |
var loginState; | |
$rootScope.$on("$firebaseAuth:login", function() { loginState = 'login' }); | |
$rootScope.$on("$firebaseAuth:logout", function() { loginState = 'logout' }); | |
$rootScope.$on("$firebaseAuth:error", function() { loginState = 'error' }); | |
return { | |
restrict: 'A', | |
compile: function(el, attr) { | |
var expState = attr.ngShowAuth; | |
function fn(newState) { | |
loginState = newState; | |
el.toggleClass('hide', loginState !== expState ); | |
} | |
fn(loginState); | |
$rootScope.$on("$firebaseAuth:login", function() { fn('login') }); | |
$rootScope.$on("$firebaseAuth:logout", function() { fn('logout') }); | |
$rootScope.$on("$firebaseAuth:error", function() { fn('error') }); | |
} | |
} | |
}); |
<style> | |
.hide { display: none; } | |
</style> | |
<script> | |
// include the waitForAuth module as a dependency | |
angular.module('myApp', ['waitForAuth']) | |
// you can use waitForAuth directly from your scripts | |
.controller('myController', function(waitForAuth) { | |
waitForAuth.then(function() { | |
/* do something after auth completes */ | |
}) | |
}) | |
</script> | |
<!-- and you can use the directives in your views --> | |
<div ng-cloak-auth>Authentication has resolved.</div> | |
<div ng-show-auth="login">{{user.id}} is logged in</div> | |
<div ng-show-auth="logout">Logged out</div> | |
<div ng-show-auth="error">An error occurred during authentication</div> |
Seriously. Killer. Thanks!
Upgraded this to work a bit more reliably. Is also now a drag-and-drop plugin suitable for angularFire, angularFire-seed, and generator-angularfire installs.
Sometimes $firebaseSimpleLogin:logout fires before waitForAuth being registered then that promise is never resolved and ng-show-auth is never showed.
@katowulf do u know what could be the problem?
I solve this calling waitForAuth service into app run()
waitForAuth is 'undefined' when I try calling it from my controller, even though I have included 'simpleLoginTools' as a dependency for my app module.
Any ideas?
Hi, I'm having issues with this module and ui-router. I have view setup like this:
app.config(['$stateProvider',
function($stateProvider) {
$stateProvider.state('home', {
url: '/home',
views: {
"main": {
controller: 'HomeController',
templateUrl: 'home/home.tpl.html'
},
"top-nav": {
controller: 'HomeController',
templateUrl: 'home/home-topNav.tpl.html'
}
},
data: {
pageTitle: 'Home'
},
resolve: {
currentUser: ["simpleLogin",
function(simpleLogin) {
// $getCurrentUser returns a promise so the resolve waits for it to complete
return simpleLogin.getCurrentUser();
}
]
}
});
}
]);
My top-nav template looks like this:
<nav class="navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" ui-sref="home">Home</a>
</div>
<div class="control-group nav navbar-nav navbar-right">
<button class="btn btn-default navbar-btn" ng-cloak ng-show-auth="['logout','error']" ui-sref="login">Log In</button>
<button class="btn btn-default navbar-btn" ng-cloak ng-show-auth="login" ng-controller="LoginController" ng-click="logout()">Log Out</button>
<button class="btn btn-default navbar-btn" ng-cloak ng-show-auth="login" ng-click="createStory()">Create Story</button>
</div>
</div>
</nav>
The problem is that ng-show-auth directives are not working. They resolve to 'logout' state even though the user is logged in. When I remove 'resolve' from my route state config, directives work fine. Can you help please?
Updated for AngularFire 0.6 (releasing this coming week)