1

I am using UI Router Multiple Views concept.

The documentation says that i can have resolve on individual views. As you can see in my plunker, I have a resolve on my child view. The resolve returns a promise, which in my case, is resolved in the parent controller. I have simulated my problem with a setTimeOut. Basically, after 5 seconds, the child view should load (with an alert saying "In Child State") but it doesn't !!!

Relevant code is below but please instead refer to Plunker.

'child@parent': {
    template: '<h4>This is Child State</h4>',
    controller: childCtrl,
    resolve: {
        trd: function(tradeFactory) {
            console.log('in resolve of child');
            return tradeFactory.ready();
        }
    }
 }
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
TkNeo
  • 415
  • 1
  • 7
  • 16

1 Answers1

1

(Check updated and working plunker) The point here is:

all resolve must be already resolved, before the views (with its controllers) are rendered

And that is not true in your scenario. In fact, there is a race condition, ending up in the deadlock.

  1. one view is waiting for a resolve (is provided with a promise)
  2. other view's controller is ready to trigger resolve (make a promise resolved), but... it cannot be triggered, while waiting for its sibling

The original snippet

views: {

  '': {
    ...
    // inside of this, you expect to resolve the below promise
    controller: parentCtrl
  },


  'child@parent': {
      ...
      resolve: {
          trd: function(tradeFactory) {
              // this is a promise waiting for resolve
              // implemented in parent controller ... deadlock
              return tradeFactory.ready();
          }
      }
  }

So, the above is not working. We have to do all inside of the resolve, e.g. this way:

views: {

  '': {
    ...
    controller: parentCtrl,
    // here do the resolve
    resolve: {
      parentReady: function(tradeFactory){
        setTimeout(function(){ 
          tradeFactory.ResolveReady()
        }, 1500); 
      }
    }
  },


  'child@parent': {
      ...
      resolve: {
          trd: function(tradeFactory) {
              console.log('in resolve of child');
              return tradeFactory.ready();
          }
      }
  }

There is updated plunker

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • thanks a lot for the answer. In my workflow the uesr will spend some time on parent view before they go open the child view. Child view needs a ton of data but putting it my parent's resolve is not a good idea. In fact as the user is working on parent view we should load this child data in the back. Thats why i am resolving the promise from parent controller as opposed to in parent's resolve. Any other suggestions on how to do this ? – TkNeo May 15 '16 at 14:13
  • The way to go, is to change the usage of UI-Router. In this scenario you should NOT play as you do - with two views in one state. You should split that into **two states** with *one view*. That will in fact simplify that all, will really use the power of UI-Router and resolvers *(and mostly make it easy to understand after few months;)*. So, introduce child state.. all will be solved... this is one of examples http://stackoverflow.com/q/28800644/1679310 – Radim Köhler May 15 '16 at 14:23
  • I have thought a lot about whether two do 2 states or 2 views (there will be more children added in future). I keep going back and forth b/c I dont like the idea of changing URLs as users go form parent -> child1 -> parent -> child 2. So i thought views is the way to go. If i converted the child view to state, how will i resolve my child promise from parent ? That problem still remains doesn't it ? (The data loading needs to happen in parent in the background and not on child resolve. Child needs to just wait until parent resolves the promise) – TkNeo May 15 '16 at 16:11
  • Look, you have to play. I gave you some plunkers to try yourself.. But the trick (the change you have to make) with two states is: resolve of parent happens first. It will not be **blocked by child state**. They are independent and that is what we want. We can use a resolve param from parent state in child state as well... and that could properly handle the dependency. Try it. you will see that two states are the way how to split that issue – Radim Köhler May 15 '16 at 16:15
  • 1
    Changed it from View to States and life has never been better. – TkNeo May 20 '16 at 00:53