Skip to content

Substate routing RFC - #40

Closed
jonathanKingston wants to merge 1 commit into
emberjs:masterfrom
jonathanKingston:substate-routing
Closed

jonathanKingston wants to merge 1 commit into
emberjs:masterfrom
jonathanKingston:substate-routing

Conversation

@jonathanKingston

Copy link
Copy Markdown
Contributor

@stefanpenner

Copy link
Copy Markdown
Member

would Components with enhanced async handling, act as one of these substates?

@jonathanKingston

Copy link
Copy Markdown
Contributor Author

@stefanpenner that wasn't really the intention no, I'm not really seeing how that would fit into the mix however I'm open to building that in certainly. Unless of course you mean things like wizard style interfaces, which certainly would be a use-case.

The main use-case is for pages within pages, mostly modals where businesses change their mind on it's usage and large amounts of code needs to be refactored for something that to a product owner looks a small change.

@stefanpenner

Copy link
Copy Markdown
Member

Cc @ef4 We chatted about this problem briefly

@jonathanKingston

Copy link
Copy Markdown
Contributor Author

@stefanpenner is that the direction you were thinking for components question?

@MiguelMadero

Copy link
Copy Markdown

I dont like the idea of reserving a URL, I think it could create a lot of confusion for something that may never happened and we are trying to avoid in the first place. Seems more like an edge case.

@jonathanKingston

Copy link
Copy Markdown
Contributor Author

@MiguelMadero you are probably right, I just thought it covered my use where by the page could be converted at any point.
Any bigger development company can probably resolve that kind of thing with coding standards or linting.

@MiguelMadero

Copy link
Copy Markdown

@jonathanKingston sorry, I didn't mean to sounds like your use case wasn't important. You stated the reasons in the RFC. I was just trying to balance how easy it's to learn something another concept vs the value it would bring based on the probability of that being needed. Overall I like the idea behind the RFC.

Another way of achieving something similar is by using nested-routers. Using login as an example, you could have all of the login flow handled by a different router. This different router would use a different location strategy (e.g. instead of history/hash it could use none or queryStrings. See the Readme for details. The advantage of having a full router, is that you could have routes and resources under login. A typical login is more than a single screen where you have the option to register, recover your password or maybe have two-phase authentication, all of those screens could be different routes with their own templates and controllers/components.

@jonathanKingston

Copy link
Copy Markdown
Contributor Author

@MiguelMadero that is fine, it can always be added later if it was needed anyway.

If multiple substates were used at once the data would need to be stored outside the global areas currently used to store state (query string, url path and hash), as it would cause data to leak into the other routes if they are used.
If this were to happen, I would suggest a self destructive in memory store as soon as a normal transition happens.
The other two alternatives suggested would cover this use case of having resources too. However I would prefer to add a new type of route for resources:

Router.map(function() {
  this.subResource('login', {path: '/login'}, function () {
    this.subState('second-factor');
  })
});

This would setup the following sub state routes:

  • login
  • login.index
  • login.second-factor

My only worry with this is persisting state on page refresh:

  • Is it needed?
    • I would much prefer for the application writer to have to manage routing the user back to the sub state and the default to be that the sub state closes (Adverts and modals very rarely persist a page reload).
  • State would belong to the normal route and/or application (For example a login screen is a global state which wouldn't matter what page is presented below; this wouldn't be true for a edit user modal)

The problem I think with the nested routers solution is the complexity of setup (Which could potentially be resolved with several conventions however).

@MiguelMadero

Copy link
Copy Markdown

@jonathanKingston the issue with persisting state or not could be resolved based on how do we configure the router. For cases where we don't need to persist the state we could simply set the location to none:

   App.SecondaryRouter = Ember.Router.extend({
        location: 'none'
    });

However, I'm proposing we create 2 different location types to better support persisting state without conflicting with the main router. One of them is to persist to localStorage. The data would look like this:

key: myAppNamespace.secondaryRouter
value: path/to/route

An alternative approach is to simply use the query string, but encoding the values in a way that doesn't conflict with other routers, for example:

mysite/products/climbingShoes?secondaryRouter="path%2Fto%2Froute"

The problem I think with the nested routers solution is the complexity of setup (Which could potentially be resolved with several conventions however).

I agree. It's too early and simply a POC. I think all of that could be simplified with conventions and better naming. I like your suggestion of using subResource or subRoute. This looks simpler than having a different Router.map. Something nice about the subRouter approach is that once you're inside a subRoute all the transitions within it, as long as it's for a route defined for the same subRouter will be handled inside the same outlet.

@tomdale

tomdale commented Jun 7, 2015

Copy link
Copy Markdown
Member

After reviewing this in depth with the core team, we feel like this doesn't quite pass the bar in terms of unlocking new functionality at the cost of the complexity that it adds.

In particular, we feel that with the introduction of the {{component}} helper, similar functionality can be achieved with a computed property, that helper, and components.

We would love it if you could try to solve the problems that motivated this RFC using that approach, and open issues with use cases that you aren't able to achieve.

@tomdale tomdale closed this Jun 7, 2015
@jonathanKingston

Copy link
Copy Markdown
Contributor Author

The {{component}} helper can certainly help rendering of substates as you mention with computed properties or similar solution.

However the main rationale for this RFC was the ability to create standard links to a specific substate so that an application can provide clean separation to the substate such that it could turn into a normal route if it needed to in future.

The best implementation I feel would be available for the computed property solution would likely pollute the application namespace (assuming the substate was global) via a mixin perhaps. Personally I don't think this could scale if I worked at a company which required lots of these (I used to, but not currently).

For me the isolation of the modal into a route of its own whilst still on the same route that triggered the modal is the only way I can think of to make this scale.
However, I would be happy to hear some thoughts on your direction on this.

@tomdale

tomdale commented Jun 22, 2015

Copy link
Copy Markdown
Member

@jonathanKingston One thing I don't understand—how do you "create standard links" but not modify the URL (per the introductory sentence of your RFC)?

@jonathanKingston

Copy link
Copy Markdown
Contributor Author

@tomdale standard template link, such that a developer and template author doesn't need to know the implementation so much.
So a substate gets it's own route name just like any other.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants