How do you set up controller selections when routing directly to a child state in SproutCore?

不羁岁月 提交于 2019-12-24 05:33:06

问题


If I have a route to a state deep in the application, how do I ensure that the proper controller set up has been done although I'm going to enter the inner state directly?

For example,

  • state A
    • state a, representRoute: 'a'
    • state B
      • state b, representRoute: 'a/b'
      • state C
        • state c, representRoute: 'a/b/c'
        • state D
          • state d, representRoute: 'a/b/c/d
          • state E

As you can see you can route directly to states 'a', 'b', 'c' or 'd', but what you can't see is that normally you would go between these states by selecting an item in a controller, which would then trigger a state transition to the deeper state. The problem then is that when you go directly to state 'd' none of your controllers' selections are set up.

So far I've used enterStateByRoute in state 'a' to set the selection of the first controller and then had to use enterStateByRoute in state 'b' to do the selection of the first and second controllers, etc. all the way to enterStateByRoute in state 'd' to do the selection of each controller all the way along. This is quite wasteful, because I end up repeating the same code in each enterStateByRoute.

What is the best way to set the controller selection to match the directly routed state?


回答1:


I was able to improve the situation greatly once I realized that enterStateByRoute is called on all parent states in the chain when routing. This means that if state 'c' matches the route, state 'A' will be entered, followed by state 'B' and state 'C' before finally entering state 'c' last. What I didn't realize before was that each of these states is passed the SC.StateRouteHandlerContext object as it is entered allowing you to either check the context in enterState or implement enterStateByRoute in any of the states.

My solution then was to add enterStateByRoute to state 'A' to set the first controller, add enterStateByRoute to state 'B' to set the second controller, etc. For example, in this way, any state past state 'A' is guaranteed to have the first controller selection set and I don't have any duplicated code down the chain.

For example,

// … 
state_A: SC.State.extend({
  initialSubstate: 'state_a',

  enterStateByRoute: function (context) {
    // select object on controller 1 since we are routing
  },

  state_a: SC.State.extend({
    representRoute: 'a',

    enterStateByRoute: function (context) {
      // do setup for state 'a' specific to routing
    }
  }),

  state_B: SC.State.extend({
    initialSubstate: 'state_b',

    enterStateByRoute: function (context) {
      // select object on controller 2 since we are routing
    },

    state_b: SC.State.extend({

      enterStateByRoute: function (context) {
        // do set up for state 'b' specific to routing
      },
// …

The only problem I encountered was that because I had bound all my controllers together, the selection change doesn't propagate immediately and so I would select an object on a controller in the first state, enter the next state and find that the bound controllers' content would not yet have updated.

So I could have waited for bindings to flush by returning an SC.Async object in enterStateByRoute and used this.invokeLast(function () { this.resumeGotoState(); }) to go to the next state at the end of the run loop, but instead I took a declarative approach and simply set/unset each controller's content as I enter/exit the appropriate state.



来源:https://stackoverflow.com/questions/16698300/how-do-you-set-up-controller-selections-when-routing-directly-to-a-child-state-i

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!