2

I'm new to angular and I'm trying to use angular ui router. When I navigate to / I get this abstract state as my $state.current: Object {name: "", url: "^", views: null, abstract: true}. Is there anyway around this so that my current state is files? Here is my code:

(function() {
    'use strict';

    angular.module('carton', [
        'ui.router',
        'carton.controllers',
        'carton.services',
        'carton.directives'
    ]).
    config([
        '$stateProvider',
        '$urlRouterProvider',
        function(
            $stateProvider,
            $urlRouterProvider
        ) {
            $urlRouterProvider.otherwise('/');
            $stateProvider.
            state('files', {
                url: '/',
                templateUrl: 'partials/files.html',
                //controller: 'FilesCtrl'
                access: {
                    isFree: false
                }
            }).

            state('login', {
                url: '/login',
                templateUrl: 'partials/login.html',
                controller: 'loginCtrl',
                access: {
                    isFree: true
                }
            }).

            state('register', {
                url: '/register',
                templateUrl: 'partials/register.html',
                //controller: 'RegisterCtrl'
                access: {
                    isFree: true
                }
            });

        }
    ])

    .run(['$rootScope', '$state', 'UserService',
        function($root, $state, userSrv) {
            $root.$on(
                '$locationChangeSuccess',
                function(event) {
                    console.log($state.current);
                    if (!$state.current.access.isFree && !userSrv.isLogged) {
                        $state.go('login');
                    }
                }
            )
        }
    ]);
})();

2 Answers 2

2

I created a plunker, which should show how to. There are 2 main parts of that solution described below.

We can use some special settings on state definition, BUT they have to be nested in the data object. See the:

Attach Custom Data to State Objects

Adjusted state def would be:

state('files', { 
  ...
  data: {           // here we do nest the custom setting into "data"
    access: {
      isFree: false
    }
  }
})

.state('login', {
  ...
  data: {
    access: {
      isFree: true
    }
  }
})

Also, the more suitable event to listen would be $rootScope.$on('$stateChangeStart', ... Here is an example how to do that:

this could be the implementation in our case:

.run(['$rootScope', '$state', 'UserService',
    function($root, $state, userSrv) {

      $root.$on('$stateChangeStart', function(event, toState
                           , toParams, fromState, fromParams) {

        var isLoginState = toState.name === "login";
        if (isLoginState) {
          return;
        }

        var shouldRequireLogin = !userSrv.isLogged
                    && !toState.data.access.isFree;
        if (shouldRequireLogin) {

          event.preventDefault()
          $state.go('login');
        }
      })
    }
])

There is a working example (register and login available always, files only if logged-on)

Sign up to request clarification or add additional context in comments.

Comments

0

Try this, It always worked for me, Without abstract state didn't work for my requirement, so i always used an abstract state as parent state

$stateProvider.
        state('files', {
            url: '/',
            abstract: true,
            views: {
               "containerView": {
                  template: "<div ng-view=""></div>" 
                            //this ng-view loads your template 'files.html'
               }
            }
         }).
         state('files.list', {
            templateUrl: 'partials/files.html',
            //controller: 'FilesCtrl'
            access: {
                isFree: false
            }
        })

EDIT: This is from my working project

$stateProvider
            .state('classes', {
                url: '/classes',
                abstract: true,
                views: {
                    "containerView": {
                        templateUrl: 'views/desktop/classes/index.html'
                    }
                }
            .state('classes.list', {
                url: '/',
                controller: "ClassListCtrl",
                templateUrl: 'views/desktop/classes/list.html'
            })

Inside index.html i just write <div ng-view=""></div>

1 Comment

check the new code, it is in my live project working fine, it might help

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.