What is the difference between Route and RouterService?

I’ve been trying to read over the documentation to see what’s available in Ember. I’m new so I’m trying to understand why there’s a Route class and a RouterService…

When would you use either of them?

1 Like

I think it’s helpful to understand what a service in general is first, then look at the difference between a route and a router service.

A service is a very handy construct for sharing “global” state or methods throughout your app. A service is a singleton (one instance per app instance) and it can be injected anywhere within your app. This allows a service to hold state/methods that you want to access in more than one place and it can be accessed very easily with the same API. The Ember Data store, for example, is a service and can be injected into any route or component for fetching records. Another common use for a service is keeping user/authentication state (can get user/authorization state from anywhere). This a very powerful abstraction. To my knowledge there isn’t a great analog in most other SPA framworks. I think in React, for example the closest equivalent would be a provider/container component but IMO that’s a less intuitive and ergonomic way to address the same need.

Anyway, now the difference between a Route and the Router service… A route represents one “page” in the app. You can sort of think of routes as mapping an application path/URL to a template. For example your app could define a route called “users” that uses path “users/” and maps this to the “templates/users.hbs” template. A Route class is the class that defines how a route behaves when it is visited or exited. Typically this involves managing the transition (checking authorization and aborting, redirecting if necessary, etc), fetching data in the model hook, adding additional state to the controller, and binding query params to the model hook behaviors. So a single Route class is defining behavior for a single app route, which is just one route in the overall app router.

The Router service is a service that can be injected anywhere to provide state/methods for managing or learning about the app’s current routing state. For example a component could inject the router service to observe the current route or route params, or to cause a transition based on an action.

TLDR: a Route defines transition and data fetching behavior corresponding to a single app “view”, and the Router Service allows any piece of the app to view/change the app’s current routing state (what route/view the app is on, query params, etc)

Hope that helps. Definitely let me know if you have any other questions!

2 Likes

Thanks for the explanation. When working with transitions, should they be placed in the Route’s constructor with the RouterService? For example: https://api.emberjs.com/ember/3.22/classes/RouterService/events/routeWillChange?anchor=routeWillChange.

The thing is that I have tried this code and I though it’s supposed to alert when transitioning from the route. What happens is that when I move to the route the function triggers. I’ve tried to debug it by console.log(this.routeName) but it’s undefined. I think that sort of makes sense because this is unbinded in anonymous functions?

this.router.on('routeWillChange', (transition) => {
      if (!transition.to.find(route => route.name === this.routeName)) {
        alert("Please save or cancel your changes.");
        transition.abort();
      }
    })

I think the router service is less useful within a route (vs a component, etc) because routes already have a lot of APIs around this stuff. In your case you might find the Route#willTransition hook fits your needs a little better, in fact the docs use basically the same use case as an example.

1 Like

I really like that hook you just mentioned. It does everything I need to do and it’s way cleaner than attaching an event listener on the Router Service. Although, I think I read somewhere that those hooks will be deprecated soon (maybe Ember 4?)

That’s possible. I know the Ember Times recently featured an RFC to deprecate some transition related methods on route and controller but I don’t believe the willTransition hook is included.

Even if it does get deprecated soon I wouldn’t worry about it too much. Once the deprecation lands there will be plenty of time to refactor and there’s usually a solid deprecation guide on the best way to transition. So not to get all zen and “don’t worry about the future” on you but I’d stick with the happy path of the present which is willTransition :grin:

EDIT: oh and I forgot there’s also this deprecation, but that’s on the Router class and not the Route class so you should still be good I think

1 Like

Good question and very good explanation on this topic, useful for me, thanks to all! :+1:

1 Like