AngularJS: Reload ng-include after user authentica

2019-03-15 09:45发布

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>

2条回答
男人必须洒脱
2楼-- · 2019-03-15 10:00

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.

查看更多
来,给爷笑一个
3楼-- · 2019-03-15 10:13

@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();
   })
})
查看更多
登录 后发表回答