Skip to content Skip to sidebar Skip to footer

Angularjs Ui-router + State Help Needed

I have html code (code snippet 1) & JS code (code snippet 2) as below. In html I am including the partials and building a page that contains a ui-view which dynamically change

Solution 1:

If I've understood it correctly you want to display the login view with-out the other views like header, footer & side menu.

Then you could create an abstract state for the layout with your views header, footer, side-menu etc. and add a separate state for your login view.

The tricky part of the demo is the views definition in the abstract state:

abstract: true,
views: {
    '': {
        templateUrl: 'layout.html',
    },
    'header@root': {
        template: 'content for header'
    },
    'footer@root': {...}
}

What is the abstract state doing? The abstract state will load the layout template in the unnamed view in your main template and loads the other views that you'd like to share with the child states.

Each child state can then define the content view as needed and re-use the other views.

Please have a look at the demo below or this fiddle.

Note: The login in the demo is of course not secure and only there to show the view redirect handling. In your app you have to work with $http and with sessionStorage and tokens.

angular.module('demoApp', ['ui.router'])
	.run(function($rootScope, $state) {
            $rootScope.$on('$stateChangeError', function(evt, to, toParams, from, fromParams, error) {
          if (error.redirectTo) {
            $state.go(error.redirectTo);
          } else {
            $state.go('error', {status: error.status})
          }
        })
    })
	.factory('userService', userService)
	.config(routes);

functionuserService() {
	var usersMock = {
    	'testUser': {
        	username: 'testUser',
            password: '1234'
        },
        'testUser2': {
        	username: 'testUser2',
            password: '1234'
        }
    };
	var userService = {
    	user: undefined,
    	login: function(userCredentials) {
        	// later --> $http.post('auth', userCredentials).then(...)// for demo use local datavar user = usersMock[userCredentials.username]
            userService.user = ( user && ( user.password == userCredentials.password ) ) ? 
            	user : undefined;
            return user;
        },
        logout: function() {
        	userService.user = undefined;
        }
    }
    
    return userService;
}
functionroutes($urlRouterProvider, $stateProvider) {

	$urlRouterProvider.otherwise('/');
    
    $stateProvider
    	.state('root', {
        	url: '',
        	abstract:true,
            resolve: {
            	'user': function(userService) {
                	return userService.user; // would be async in a real app
                }
            },
            views: {
            	'': {
                	templateUrl: 'layout.html',
                },
            	'header@root': {
                	template: '<h1>header View<span ng-if="user"><button ng-click="logout()">logout</button></span><span ng-if="!user"><button ng-click="login()">login</button></span></h1>',
                    controller: function($scope, $state, user, userService) {
                    	$scope.user = user;
                        $scope.login = function() {
                        	$state.go('login');
                        };
                        $scope.logout = function() {
                        	userService.logout();
                            $state.go('root.home', {}, {reload: true});
                        };
                    }
            	},
                'footer@root': {
                    template: '<p>footer view</p>'
                }
            }
        })
    	.state('root.home', {
            url: '/',
            views: {
                'content': {
                    template: 'Hello at home'
                }
            }
        })
        .state('root.about', {
            url: '/about',
            views: {
                'content': {
                    template: 'about view'
                }
            }
    	})
        .state('root.restricted', {
            url: '/restricted',
            resolve: {
            	auth: function(userService, $q, $timeout) {
                
                	var deferred = $q.defer();
                	/* //with an async
                    return UserService.load().then(function(user){
                      if (permissionService.can(user, {goTo: state})) {
                        return deferred.resolve({});
                      } else {
                        return deferred.reject({redirectTo: 'some_other_state'});
                      }
                    }*/
                    
                   $timeout(function() {
                        if ( angular.isUndefined(userService.user) ) {
                            return deferred.reject({redirectTo: 'login'});
                        }
                        else {
                            return deferred.resolve(userService.user);
                        }
                    });
                    
                    return deferred.promise;
                }
            },
            views: {
                'content': {
                    template: 'this is only visible after login. Hello {{user}}!',
                    controller: function($scope, auth) {
                    	$scope.user = auth.username;
                    }
                }
            }
    	})
        .state('login', {
            url: '/login',
            templateUrl: 'views/login.html',
            controller: function($scope, $state, userService) {
            	$scope.login = function(cred) {
                	var user = userService.login(cred);
                    
                    if (angular.isUndefined(user)) {
                    	alert('username or password incorrect.')
                    }
                    else {
                    	$state.go('root.restricted');
                    }
                };
            }
        });
}
<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js"></script><divng-app="demoApp"><aui-sref="root.home"href="#">home</a><aui-sref="root.about"href="#">about</a><aui-sref="root.restricted"href="#">restricted page</a><divui-view></div><scripttype="text/ng-template"id="views/login.html"><h1>Login</h1><p>Try testUser and 1234 as credentials</p><label>Username</label><inputng-model="userCred.username"/><label>Password</label><inputtype="password"ng-model="userCred.password"/><buttonng-click="login(userCred)">login</button></script><scripttype="text/ng-template"id="layout.html"><div><divui-view="header"></div><divui-view="content"></div><divui-view="footer"></div></div></script></div>

Solution 2:

app.config(['$stateProvider','$urlRouterProvider',
  function($stateProvider,   $urlRouterProvider) {  
    $urlRouterProvider.otherwise('/login');
    $stateProvider.state('grid', {
      url: '/grid',
      templateUrl: 'resources/html/grid.html',
      controller: 'gridCtrl'
    })
    .state('chDetail', {
      url: "/chDetail/:chId",
      templateUrl: "resources/html/chDetail.html",
      controller: 'chDetailCtrl'
    })
    .state('login', { 
      url: "/login",
      controller: 'loginCtrl',
      views: {
        '': {
          templateUrl: 'resources/html/login.html'
        },
        'login-only@login': {
          templateUrl: 'resources/html/other-html.html'
        }
      }
    });
  }
])
.controller('gridCtrl', ['$scope', function($scope){
  $scope.grid =[];
}]);

I've altered it slightly. To get what you want, use views.

Then your extra bit of code would just be another ui-view, just a named one:

<divui-view="login-only"></div>

It would only appear on the 'login' state, since you specifically target it via it's name (login-only@login).

You can read more about it at the Multiple Named Views on the ui-router wiki help pages at github.

Solution 3:

very basically you can use $state for get current state like:

module.exports = function Controller($state, $scope)

$scope.currentState = $state.current;

then in your html

<p ng-if="currentState !='login'" ng-include="'${footer}'"></p>

but nested ui-router logic could be more useful.

Post a Comment for "Angularjs Ui-router + State Help Needed"