Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: Reload ng-include after user authentication (or a better way to solve issue)

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>
like image 658
Jazzy Avatar asked Oct 05 '13 23:10

Jazzy


2 Answers

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.

like image 100
Chandermani Avatar answered Nov 18 '22 22:11

Chandermani


@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();
   })
})
like image 38
Housne Avatar answered Nov 18 '22 20:11

Housne