-
-
Notifications
You must be signed in to change notification settings - Fork 408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@route
argument
#634
Comments
It works partly with This idea is navigate around current route implementation and make that one a little bit easier. My current understanding of the whole topic is, that routing needs to be re-thought within ember, at the moment it is heavily overloaded to what most people use it for. Routes have loading and error states, while the trend is more towards provider components or services (eg. I think routing should be reduced to what is required to result in a resource given the current URL, which are two parts: URL segments and query params. Those are available to routes as arguments, controllers will be eliminated, the hooks of routes are reduced, too (maybe activate/deactivate is enough - or On the other hand the routing layer should enable such experiments that @machty is running =) That's my current state of mind 😂 |
IMHO, we should go a slightly different direction here. We shouldn't expose the route directly to templates, we should add a hook that represents the named arguments to be passed into the template. I'm using the name export default class extends Route {
model() {
}
async args() {
// pseudo code
return {
model: await this.model(params, transition),
someOtherThing: this.whateverHere
}
}
@action
whateverHere() {
// zomg
}
} And that hook, returns a promise that resolves to an object whose keys are the full list of named arguments available in the template. So in the above snippet, you would be able to write |
I think exposing the route instance like that is pushing users in the wrong direction, and well as having tracked and computed state in the route. I think we would increase the possibility of mis-use and confusion. |
I'm not proposing exposing the route directly to templates. I'm proposing a |
@Gaurav0 I did not understand that nuance on first read through. I think what you said and what I said are very close. The differences (as far as I can tell) are that my proposal:
|
I love the idea of being able to pass named arguments into the route template. I'm wondering if we can get rid of the ceremony and use a decorator:
|
@jrjohnson - I think we probably could do something like that, but I personally think it makes sense to start with underlying mental model / primitive (e.g. the method you can implement). At that point, it would be pretty easy to make an addon that would provide the decorator like in your snippet (gathering the decorator implemenations and implementing the hook). |
@rwjblue My only concern is that it potentially breaks |
Nah, I don't really think this is likely to be an issue. If you don't want
When named arguments were introduced, we intentionally reserved a very large namespace that can be used for special purposes (anything starting with a capital letter, for example). I generally think less unexplainable "magic" is better, and having this turn out to be something fairly easy to remember is good IMHO. |
Ok. How about this? export default class extends Route {
model() {
}
get args() {
return {
model: this.modelFor(this.routeName),
whateverHere
};
}
@action
whateverHere() {
// zomg
}
} This should avoid triggering the model hook twice. It also makes it clear that args updates just like any computed property and is a read only property. Also what should happen if |
I don’t particularly think we should further To clarify my original snippet a bit, I think we would need some massaging to properly call |
I don't understand. I'm trying to avoid making args an async hook and reimplementing the router's current behavior.
This seems to go down the road of calling everything twice? |
I see. That is not my goal. My goal is to rationalize the current async behaviors in terms of a broader system than just
In this case, because it doesn’t help make the proposal simpler. In the general case, because it is conceptually very bizarre to exist in the first place. IMHO, it’s primary issue is that it’s attempting to provide sync access to async data.
How so? |
I wasn't trying to reimagine the entire Ember Route API but to make a focused RFC to solve the issue of requiring controllers to solve some simple issues (mostly because I know that some people will resist having to move code into controllers with RFC #632 and I want to provide an escape hatch.) If we don't change the whole Route api, just adding the |
We are, in fact, trying to reimagine the route API, as per the roadmap, both to improve accessibility and to make things fit better into the Octane model, so I think a little broader perspective is warranted at this time. A lot thoughts have been given in this area and in the rough API design @rwjblue proposed in the past already. The first time we discussed that was at least in the 2017 face-to-face. Roughly, the "end goal" (of the particular proposal) is to transition into into this: class Route {
async beforeModel(transition) { ... }
async model(params, transition) { ... }
async afterModel(model, transition) { ... }
} to this: class Route {
// TODO: do we still need before/after hooks? seems like not but TBD
async args(params, transition) { ... }
} As a transition path, you can imagine (mega hand wave) that Ember adds this to the super class: class Route {
async args(params, transition) {
if (typeof this.beforeModel === 'function') {
// TODO: deprecate or not?
await this.beforeModel(transition);
}
let model;
if (typeof this.model === 'function') {
// TODO: deprecate or not?
model = await this.model(params, transition);
}
if (typeof this.afterModel === 'function') {
// TODO: deprecate or not?
await this.afterModel(model, transition);
}
return { model };
}
} ...and that Ember will stop calling the other hooks directly, just through the class Route {
async args(params, transition) {
if (typeof this.model === 'function') {
// TODO: deprecate or not?
return { model: await this.model(params, transition) };
}
}
}
class Router {
private async transitionIntoRoute(route, params, transition) {
if (typeof route.beforeModel === 'function') {
// TODO: deprecate or not?
await route.beforeModel(transition);
}
let args = await route.args(params, transition);
if (typeof route.afterModel === 'function') {
// TODO: deprecate or not?
await this.afterModel(model, transition);
}
return args;
}
} TBD. Lots of details to figure out. Anyway, I think that's what @rwjblue is is getting it and what the "rough sketch" of the args hook API entails. I don't think anyone is trying to call everything twice. That would be both slow and incorrect (causes problem existing code didn't account for). One way or the other, the end goal is to transition away from the single model argument into allow passing arbitrary named arguments. That gets you probably 70-80% there of "routable components" and not needing controllers. It essentially turns the model into "route invokes a template-only component with args". It may even be good enough that we can deprecate controllers once this lands and when we have an alternative place for QPs to live. |
Sorry, I was not privy to past conversations regarding this topic. The roadmap is rather vague and did not mention a new Route api. Now my concern re: #632 is that we are deprecating |
@chancancode @rwjblue I've thought about it, and I've decided that I oppose explicit, overrideable routing or model resolution. Routing and model resolution that "just works" is a strength of Ember.js, not a weakness, and my quick non scientific survey indicates the community neither cares about or wants explicit routing or model resolution. I would not like to be able to write code that breaks nested model promises, for example, by accident. |
Yep, totally agree, but I don't see how this ties into the prior conversation at all. |
fwiw, @chancancode's example is basically how it works now. I recently wanted to move this underlying https://github.com/tildeio/router.js/blob/v6.2.5/lib/router/route-info.ts#L222-L234 |
I'm closing this due to inactivity. This doesn't mean that the idea presented here is invalid, but that, unfortunately, nobody has taken the effort to spearhead it and bring it to completion. Please feel free to advocate for it if you believe that this is still worth pursuing. Thanks! |
The
@model
argument that was added to route templates got me thinking... what if we could pass our own arguments from a route to a template that would also be read only?Example:
Basically the routeArgument hook would return an object that would be represented as
@route
on the template. This could greatly reduce our reliance on controllers at the top level. By freezing the object returned by routeArgument, we could enforce one way binding. Our route templates could be much more like template only components.What do people think?
cc/ @NullVoxPopuli @pzuraq @rwjblue
The text was updated successfully, but these errors were encountered: