1

My app automatically starts at the default state (that has url: "/"), obviously. Let's call it state A.

I want to hold back on that in case that a certain condition is truthy. Meaning that if x === 4 for instance then I want state B to be the first one that loads.

My problem is that by the time I check for that condition, in the app.run for instance, the default state is already being loaded and presented in the view, and only then switches to state B.

Is there any way I can hold back the state loading and kickstart it only after I check the condition ?

Omri Aharon
  • 16,959
  • 5
  • 40
  • 58
  • Won't be the `$urlRouterProvider.otherwise(function ($injector, $location) {...}` solution for you? More details about that [$urlRouterProvider](http://angular-ui.github.io/ui-router/site/#/api/ui.router.router.$urlRouterProvider). And if you need also **.run()** phase... deferred execution could be solution http://stackoverflow.com/questions/30455792/start-angular-js-route-segment-or-ui-router-after-all-translations-are-loaded – Radim Köhler May 27 '15 at 09:11
  • Could you not use a resolve in the $routeProvider and then redirect to the correct route – George May 27 '15 at 09:24
  • @RadimKöhler I'll check that and report back, thanks. – Omri Aharon May 27 '15 at 09:25
  • @RadimKöhler That's interesting and works but it doesn't trigger unless the URL doesn't match any of the states. So if I refresh on a URL that matches a state the otherwise doesn't trigger. – Omri Aharon May 27 '15 at 10:41
  • @RadimKöhler I'm talking about your first suggestion btw, looking at the 2nd suggestion now and trying to see if it can work. – Omri Aharon May 27 '15 at 10:49
  • You are right.. this is **otherwise** nature... But this is something which is close to your question. I'd say. If we want to do redirect..(when user is going to existing state) we can easily introduce some kind of redirect in the state change event - please check this http://stackoverflow.com/a/29491412/1679310 – Radim Köhler May 27 '15 at 10:55
  • @RadimKöhler Your 2nd suggestion seems to fit my scenario. I defer interception and on the `.run` phase I do my condition check, and if true I use `$location` to change the URL and then `urlRouter.listen` switches to the correct state. Post it as an answer I'll accept! – Omri Aharon May 27 '15 at 11:00
  • Really great if that helped anyhow. Great job... enjoy UI-Router Omri Aharon;) – Radim Köhler May 27 '15 at 11:11

2 Answers2

1

There is a working example

As discussed in comments we can use the native, built-in features, coming with UI-Router. One of them is $urlRouterProvider.deferIntercept(defer)

Disables (or enables) deferring location change interception.

If you wish to customize the behavior of syncing the URL (for example, if you wish to defer a transition but maintain the current URL), call this method at configuration time. Then, at run time, call $urlRouter.listen() after you have configured your own $locationChangeSuccess event handler.

I. step - STOP execution

So, we can define states in .config() phase

.config(['$stateProvider', '$urlRouterProvider','$locationProvider',
    function ($stateProvider, $urlRouterProvider,$locationProvider) {

        // States
        $stateProvider
          ...
          .state('parent', {
              ...
          })
          .state('parent.child', { 
              ...
          })
          ;
        
        ...
        // here we say STOP
        $urlRouterProvider.deferIntercept();
    }
])

II. step - init what needed in .run() - re-enable execution

This could be some naive example of run:

.run(['$urlRouter', '$timeout', '$state',
  function($urlRouter, $timeout, $state) {
    
    $timeout(function(){
      
      // here we turn all on again...
      $urlRouter.sync();
      $urlRouter.listen();
      
      // there could be some decision, driven by $http load
      // we just use some state as default target
      $state.go("parent.child");
    }, 1000)
    
}]);

Se do wait for a second and then we do re-enable all the execution and redirect to "parent.childd" ... but could be any other, based on some decision done in .run() phase

Check it here

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
0

Make use of resolve. if you are using ngRoute

$routeProvider
.when('/' ,{
    templateUrl: "templates/A.html",
    resolve:{
        "check":function($location){   
            if(x==4){ 
               $location.path('/B');
            }
        }
    }
})
.when('/B' ,{
    templateUrl: "templates/B.html"
})
.otherwise({redirectTo: '/'});
Zee
  • 8,420
  • 5
  • 36
  • 58
  • I tried going that way, but the condition is dependent on an async result, so it's not working. It shows the view anyway. – Omri Aharon May 27 '15 at 09:27