Routes and their future role in Ember


#1

Coming from this thread https://mobile.twitter.com/oligriffiths/status/993837170317234181 I decided to post my thoughts in more then just a tweet :slight_smile: and get others to reply.

Looks like there are a few ideas and projects that are rethinking the role of the Route in an Ember app. One of those early ideas was “Routable Components” and I think there is still something there that can be salvaged to make Ember a simpler and more coherent framework.

There are several ways that this could go, the two most obvious are:

  1. Route -> Component
  2. Route -> Template -> Component (https://mobile.twitter.com/Thoov/status/993733133894799361)

One downside I see to #1 is that it’s not as clear which component is associated with a route. Does that have to be set in the Route or should it be a convention like <routeName>-route component, e.g. users-route. The other issue is how to define the data and the actions on the component without that intermediate template. I modified @thoov’s gist for #2 to reflect #1 here: https://gist.github.com/knownasilya/5db86b6ddbd2c8bcabbed77567ec3798 just to get some brainstorming going.

With #2 doing ember g route <routeName> also creates a template, but that template doesn’t automatically have a component so that’s an extra step and there is no way to know if the template rendered without a component with the APIs currently in the Route. If the controller is removed, which data is passed to this template and does that data include actions as well? So there are a few unresolved questions.

I’d like to see a discussion about which convention is more fitting for Ember, or if it’s another one altogether. What other pros/cons are there for each solution?


#2

I stick with routes being just there to resolve your models and nothing else. Then, I like to think that the template-controller pairing as a container component in Redux land. It’ll always just call a bunch of presentational components inside it.

Edit:

Not sure if I’m contributing to the topic haha. Are you trying to brainstorm a possible RFC?


#3

One thing worth pointing out about option 2 is that with the advent of @name arguments, you can pass freeform arguments to template-only components.

You could imagine a router API like:

export default class extends Route {
  async args(params, queryParams) {
    return RSVP.hash({
      person: this.store
        .find("person", params.person_id)
        .filter("gt", queryParams.age_gt)
    })
  }
}

Which would produce a @person in the template. In this case, and especially with outerHTML template-only components, it’s hard to see why it needs a component class.


#4

I agree mostly, but there are two important scenarios to consider:

  1. Component Hooks (didInsertElement,didReceiveAttrs, etc)
  2. Actions

I could see “route templates” becoming template only components, with the option to add a component class for the didInsertElement behavior, but for actions I’m not so sure. Also didReceiveAttrs would fire on QP changes in Route (?).

Maybe an actions object that has all of the actions which are bound to the route if no component class, otherwise to the component (that sounds kinda bad), or maybe the component actions get merged with the route actions (if actions defined in the component class) … not really sure.


#5

Hello! :wave:

I have been thinking about this topic lately.

One thing that is very clear for me is that controllers must die. They are very difficult to explain to people that are just getting started with Ember.

I believe routes should be just a “type of component”.

They should behave exactly the same as other components, with regular event hooks (didInsertElement etc), but with some additional hooks to support components to be routable.

The params that we current receive on the model hook, could just be an argument to the component, as well as the query params. They would be accessible via this.args, similarly to glimmer components.

Managing QueryParams could be extracted to a service that would be injected into the component, lots of work here, but the learning curve for this programing model would way lower.

One thing that one would need to figure out is how the loading and error states would play into this “routable components”.

Something like this would be very interesting:

export default class extends RouteComponent {
  async data() {
    return RSVP.hash({
      person: this.store
        .find("person", this.args.params.person_id)
        .filter("gt", this.args.queryParams.age_gt)
    })
  }

  didInsertElement() {
    console.log('element inserted into dom!'); 
  }

  sayHello() {
    // not sure how to access the data here, but would be nice to
    // have it as this.data.person.name or something like that.
    console.log('Hello'); 
  }
}
{{log @params}}
Hello {{data.person.name}}!
<button onclick={{action this.sayHello}}>Say Hello</button>

Anyway, these are just some thoughts. I’m sure there are many flaws on my example above, but a simpler programing model would come a long way.