29

How can transitionToRoute be called cleanly from within an Ember component?

It works with injecting a controller into the component and calling the controller's transitionToRoute function, however I'd like something a little more elegant if possible.

What it currently looks like inside the component's javascript:

// this.controller is injected in an initializer
this.controller.transitionToRoute("some.target.route.name");

What would be nicer in the component's javascript:

transitionToRoute("some.target.route.name");

One goal is do this without using sendAction as this particular component has a single purpose and should always transition to the same route. There's no need for any other Ember artifacts to be aware of the route this component always transitions to, there's no need for the associated indirection. The responsibility for the target route is owned by this component.

Eliot Sykes
  • 9,616
  • 6
  • 50
  • 64
  • Related question that may be of interest to readers: http://stackoverflow.com/questions/22389384/transitiontorouteroute-from-inside-component – Eliot Sykes Jun 12 '15 at 12:29

5 Answers5

65


UPDATE Please see the other more recent answers for how to achieve this with less code in newer Ember versions, and vote those up if they work for you - Thanks!



Inject the router into the components and call this.get('router').transitionTo('some.target.route.name').

To inject the router into all components, write an initializer at app/initializers/component-router-injector.js with the following contents:

// app/initializers/component-router-injector.js
export function initialize(application) {
  // Injects all Ember components with a router object:
  application.inject('component', 'router', 'router:main');
}

export default {
  name: 'component-router-injector',
  initialize: initialize
};

Sample usage in a component:

import Ember from 'ember';

export default Ember.Component.extend({
  actions: {
    submit: function() {
      this.get('router').transitionTo('some.target.route.name');
    }
  }
});
Eliot Sykes
  • 9,616
  • 6
  • 50
  • 64
  • 1
    For 2017 readers: The problem with `sendAction` is that you have to keep bubbling that up if your components are nested. If you can send an action directly to the route from the component, it becomes a non-issue. Ember will eventually have routable components that allows you to talk directly to the route. Until then, use the the `ember-route-action-helper` to call a method directly on the route that your component exists on - such as `transitionTo('name-of-route')`. Read more here: http://dockyard.com/blog/2016/02/19/best-practices-route-actions – PhillipKregg Jul 20 '17 at 17:20
13

Jan 22, 2018 update
As of Ember 2.15, phase 1 of the public router service is implemented.
Transition to a route from inside a component:

import { inject as service } from '@ember/service';

export default Ember.Component.extend({
  router: service(),

  actions: {
    someAction() {
        this.get('router').transitionTo('index');
    }
  }

});
myartsev
  • 1,207
  • 2
  • 13
  • 23
5

Use router: service()

instead of router: service('-routing')

import Component from '@ember/component';
import {inject as service} from '@ember/service';

export default Component.extend({
  router: service(),

  actions: {
    onClick(params) {
      let route = this.getMyRoute(params);
      this.get('router').transitionTo(route);
    }
  }
});
ecairol
  • 6,233
  • 1
  • 27
  • 26
3

If you want to use the router only in a specific component or service or controller, you may try this:

Initialize an attribute with the private service -routing. The - because it's not a public API yet.

router: service('-routing'),

And then inside any action method or other function inside the service or component:

this.get('router').transitionTo(routeName, optionalParams);

Note: It'll be transitionToRoute in a controller.

Jayant Bhawal
  • 2,044
  • 2
  • 31
  • 32
2

You can use container to get access to any needed part of application. To get application controller :

this.container.lookup('controller:application')

But what about structure of application - components should generate events - so my opinion it's better to use sendAction. Cause in future you can get situation, when you need to filter such behavior ( for example ) or other application-specific logic before transition

Vasiliy vvscode Vanchuk
  • 7,007
  • 2
  • 21
  • 44
  • 2
    This is not recommended as it uses an internal API that could break. Actually the access to the container started to be deprecated on Ember 2.3 I think, and it's now replaced with a different interface (`getOwner` I think). – Ernesto Oct 13 '16 at 01:16