dotJEM / angular-routing

Enhanced state based routing for Angular applications!
https://dotjem.github.io/angular-routing/
MIT License
75 stars 9 forks source link

Resolve parents and children state data. #54

Closed soundstep closed 11 years ago

soundstep commented 11 years ago

Just an FWI. I know the ui.router guys are working on this to find a better solution.

When you have both a parent state and a child state that pull data using the resolve property, you sometimes would like to wait that the parent is resolved before the child is pulling its own data.

For that matter, I used the following gist which work well, but maybe you'd want to implement something neater than that.

Here is the gist, hope that makes sense.

https://gist.github.com/MattWalker/6106393

jeme commented 11 years ago

Have you tried without the gist?...

angular-routing actually does merge resolves (or it should do so at least), but I am yet not sure exactly what the outcome is, but since I have not had a great scenario I have not been able to test out what really happens...

So it would be great with an actual scenario, even better a jsfiddle that presents that. So I can actually test and maybe fix any potential bugs... I just simply haven't had the luck to produce such a scenario my self.

Right now I am not entirely sure if we end up with a list of promises for locals or actual resolved values in these kind of cases. If the later is the case, AFAIK they should actually resolve parent fully before child, but this is quite complex and a "resolver" would properly be able to make that complexity more "tangible"...

soundstep commented 11 years ago

Well yes, I found the gist because the resolve where not made one after the other, at least with ui.router, which I was using at that point. I didn't try with your router.

Working night and day on a project right now, not much time. But I'll make an example as soon as I can.

jeme commented 11 years ago

I am going to close this one for now as there is some tests that at least verifies that resolved values are inherited from parent and down... And i am positively sure they also resolves in a sequential manner...

There is also added some caching support through a $resolve service so that we don't make server requests unnecessarily for unchanged parents.

Not yet documented as that is to early to figure out it's external role in e.g. transitions etc. Currently it is possible to clear the cache and push values/promises to it from transitions. But pushing values for changed states currently has no meaning as it just overwrites the values again, ideally it should be possible to push a value that will then be resolved as is in the resolve phase.

And that is what I am currently working towards.

soundstep commented 11 years ago

I still have to use that gist otherwise, the data are not loaded from parent to children in the right order. But I'll make tests and let you know.

jeme commented 11 years ago

I have added a number of tests that indicates that it works as it should... They don't directly test it, but instead they test that you can use resolved values from parents in resolve of children... like so:

  $stateProvider
    .state('top', {
      views: { 'tpl': { template: "tpl" } },
      resolve: { val: function () { return "first"; } }
    })
    .state('top.mid', {
      views: { 'tpl': { template: "tpl" } },
      resolve: { val: function (val) { return val + ".second"; } }
    })

   var top_resolve = { val: "first" };
   var mid_resolve = { val: "first.second" };

And / Or

  $stateProvider
    .state('top', {
      views: { 'tpl': { template: "tpl" } },
      resolve: { topval: function () { return "first"; } }
    })
    .state('top.mid', {
      views: { 'tpl': { template: "tpl" } },
      resolve: { midval: function (topval) { return topval + ".second"; } }
    })

   var top_resolve = { topval: "first" };
   var mid_resolve = { topval: "first", midval: "first.second" };

And so forth... Which has been a requested feature on UI-Router as well... But since these gives the expected outcome, it gives me confidence that things work as intended.

soundstep commented 11 years ago

I would be good to add timeouts in each resolve, with different values, as these resolve properties does not represent a case close to the reality, where a resolve takes time to get something back from a server.

I also use sticky views, if that matters.

Hope that makes sense!

jeme commented 11 years ago

Timeouts are problematic in tests as they either delay or you need to flush in which case they don't really provide you what you wan't... however, here is a demo with 1s delays: http://plnkr.co/edit/CPEKaqfdZREIvu7A3hQr?p=preview

Not using Sticky views though, but that should matter little in this case... (I couldn't quite come up with a proper example on using sticky views together with it)

However ones you get to the views, (be it loading the controller or calling refresh) all resolves will have completed. meaning you will see things happening instantly at that point, this is because views are not updated until the entire state transition is completed fully which in turn means all resolves have run...

And in turn from there, refresh/updates may not necessarily be issued in a top down manner, this very much depends on the configuration. (The order could be changed though)

So taking the example plunker, if you go directly from the front page to the about 42 with a calculation you will see roughly a 2 second delay before the first view is rendered instantly followed by the second view. If you add breakpoints in the resolves however you will see a 1s delay between the parent and the children.

What i did discover during this though is that there is no guards against starting a second transition while the first one is in progress... (if re click the links rapidly). Which causes an error. #59

Hope that helps, otherwise see if you can't modify the plunker to show the issue your having... Because right now I can't quite see where there could be issues... So it must be a very specific situation...