Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot read property '@' of null when using $state in onEnter

I am get the following error from the angular-ui-router:

TypeError: Cannot read property '@' of null
...
TypeError: Cannot read property '@main' of null
...

I have done some research on what could be the cause of this error and have come to the conclusion that the problem lies with the the fact that I do a redirect when a condition is false through a $state.go(state) during an onEnter of another state.

Here are some discussions concerning the same issue on github:

  • https://github.com/angular-ui/ui-router/issues/1234
  • https://github.com/angular-ui/ui-router/issues/1434

I tried some of the suggestions, but they are not working. They don't seem to provide a solution, but just point out the problem, and according to this github discussion it should be resolved, but I can't seem to get it to work.

I am using AngularJS v1.2.24 and ui-router v0.2.11.

Using the following code (simplified):

.state('main', {
    abstract: true,
    url: '/main',
    templateUrl: '/main/_layout.html'
})
.state('main.home', {
    url: '/home',
    templateUrl: '/main/home/home.html',
    controller: 'HomeCtrl',
    onEnter: function ($state)
    {
        if (condition === true){
            $state.go('main.catch')
        }
    }
})
.state('main.catch', {
    url: '/catch',
    templateUrl: '/main/catch/catch.html',
    controller: 'CatchCtrl'
})

Is there a way to get this to work? Or should I consider a completely different approach to achieve the same result?

P.S.: A possible fix is to do the following in the controller,

$scope.$on('$stateChangeSuccess', function(){
    // conditional redirect here
}

But I don't want to do it in the HomeCtrl.

like image 339
bohem.be Avatar asked Nov 09 '22 18:11

bohem.be


1 Answers

I have encountered a similar situation, and solved it this way:

.state('main.home', {
    url: '/home',
    templateUrl: '/main/home/home.html',
    controller: 'HomeCtrl',
    onEnter: function ($state)
    {
        if (condition === true){
            $timeout(function() {
                $state.go('main.catch')
            )};
        }
    }
})

The trick is that you want to let the original state change finish rather than trying to redirect in the middle of the state change. The $timeout allows the original state change to finish, and then immediately fire off the change to the desired state.

like image 188
DavidA Avatar answered Nov 15 '22 04:11

DavidA