I am really just learning Angular and I am attempting to create an app that limits content access based on authentication. I have the authentication part working (also using the Laravel PHP framework), but I am having an issue "reloading" certain pieces of content based on auth status, namely after a successful authentication.
Initially, what I am trying to do is update the main navigation menu after a user logs in. I am sure there is a better approach, but what I have so far is a view returned from the server that has different navigation elements depending on whether the user is logged in or not, then loading that into an element with ng-include.
There is an option to log in, which loads a login form into the ng-view. After the user logs in, I would like to refresh the ng-include with the view from the server.
Is there a way to reload that template in the ng-include after a successful login?
Please feel free to recommend a better technique to solving this if this is the wrong approach. Of course, this would be very easy to do in jQuery, but I would prefer to do things the Angular way.
Here is some of my code so far:
index.html:
<div class="container" ng-controller="appController">
<div id="nav" ng-include src="menuUrl()"></div>
<div class="row">
<div class="span3" ng-include src="'partials/brands.html'" ng-controller="brandController"></div>
<div class="span9" ng-view></div>
</div>
</div>
Some controllers:
.controller('appController', function($scope){
$scope.loggedIn = false;
$scope.menuUrl = function() {
return "partials/nav.html";
};
})
.controller('loginController',function($scope, $sanitize, $location, Authenticate, Flash){
$scope.login = function(){
Authenticate.save({
'email': $sanitize($scope.email),
'password': $sanitize($scope.password)
},function() {
$location.path('/products')
Flash.clear()
sessionStorage.authenticated = true;
},function(response){
Flash.show(response.flash)
})
}
})
.controller('logoutController',function($scope, $location, Authenticate, Flash){
$scope.logout = function (){
Authenticate.get({},function(response){
delete sessionStorage.authenticated
Flash.show(response.flash)
$location.path('/login')
})
}
})
Services:
.factory('Authenticate', function($resource){
return $resource("/service/authenticate/")
})
.factory('Flash', function($rootScope){
return {
show: function(message){
$rootScope.flash = message
},
clear: function(){
$rootScope.flash = ""
}
}
})
App:
.config(['$routeProvider',function($routeProvider){
$routeProvider.when('/', {
templateUrl: 'partials/home.html',
controller: 'homeController'
})
$routeProvider.when('/login', {
templateUrl: 'partials/login.html',
controller: 'loginController'
})
$routeProvider.when('/logout', {
templateUrl: 'partials/logout.html',
controller: 'logoutController'
})
$routeProvider.otherwise({redirectTo :'/'})
}])
.config(function($httpProvider){
var interceptor = function($rootScope,$location,$q,Flash){
var success = function(response){
return response
}
var error = function(response){
if (response.status == 401){
delete sessionStorage.authenticated
$location.path('/')
Flash.show(response.data.flash)
}
return $q.reject(response)
}
return function(promise){
return promise.then(success, error)
}
}
$httpProvider.responseInterceptors.push(interceptor)
})
.run(function($http,CSRF_TOKEN){
$http.defaults.headers.common['csrf_token'] = CSRF_TOKEN;
})
Laravel view:
<ul class="nav nav-tabs">
<li><a href="#/">Home...</a></li>
@if(!Auth::check())
<li><a href="#/login">Log-in</a></li>
@else
<li><a href="#/logout">Log-out</a></li>
@endif
<li><input name="search" id="search" type="search" placeholder="Search products..." />
</ul>
You can start with raising an event when user login is success on the rootscope using broadcast method
$rootScope.$broadcast('userLoggedIn',{user:user});
On the appController
you can subscribe to the even
$scope.$on("userLoggedIn",function(event,args) {
$scope.menuUrl=null;
$scope.menuUrl="partials/nav.html";
});
this also implies that change your menuUrl to a property in you controller and html binding.
Alos, if you can define multiple server views for logged in and anonymous user, then you can just flip the view on user login.
@Chandermani 's answer is almost close, in fact, you can just add some random params to force refresh, just like this:
app.controller('appController', function($scope){
var getMenu = function(){
var random = Math.random();
return "partials/nav.html?r=" + random;
}
$scope.menuUrl = getMenu();
$scope.$on('userLoggedIn', function(){
$scope.menuUrl = getMenu();
})
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With