17

How do I transition to a route pragmatically from inside a component action?

I tried to use @get('controller').transitionToRoute('images'), but the controller refers to the component itself. I understand that components should be self contained, so should I be using a view instead to interact with controllers/routes better?

Example

App.ImageEditorComponent = Ember.Component.extend
  ...
  actions:
    delete: ->
      App.Files.removeObject(object)
      @transitionToRoute('images') # This throws an exception
  ...
al3xnull
  • 866
  • 1
  • 13
  • 29
  • I feel like the idea is that a component shouldn't know about the host controller's actions. You might want to send a message instead. – aceofspades Mar 14 '14 at 23:58
  • @aceofspades Quite possibly. So far I've understood that views may know of the controller, but the controller may not know about the view in Ember. Could you show me an example as an answer? Curious how this would work; have a vague idea. – al3xnull Mar 15 '14 at 23:32
  • @aceofspades Assuming you mean something like [this](http://emberjs.com/guides/components/sending-actions-from-components-to-your-application/) then I suppose instead of the `currentControllerBinding` I could set a `fileDeletedAction` and then `this.sendAction('fileDeletedAction')`. – al3xnull Mar 15 '14 at 23:44
  • Did just that. I like the de-coupling more. Very easy to change to another location in a different section of the application. Please write answer. – al3xnull Mar 15 '14 at 23:52

6 Answers6

9

You could pass the controller in via a binding and then access it inside your component like so:

{{image-editor currentControllerBinding="controller"}}

App.ImageEditorComponent = Ember.Component.extend
  ...
  actions:
    delete: ->
      App.Files.removeObject(object)
      @get('currentController').transitionToRoute('images')
  ...
Kris Khaira
  • 132
  • 11
chopper
  • 6,649
  • 7
  • 36
  • 53
  • Works for me in Ember 1.8.1. – Kris Khaira Dec 03 '14 at 14:17
  • 2
    This ins't the right awnser I searching. Maybe have some another way. – heat Apr 29 '16 at 21:23
  • I would note this isn't the correct action anymore since Ember has change quite a bit. For those whom were Ember 2+, I'll mark a more correct answer. Welcome to try the above answer if you are still using 1.13. – al3xnull Aug 30 '17 at 18:50
8

Create action on parent controller.

export default Ember.Controller.extend({
  actions: {
    transInController() {
       this.transitionToRoute('home')
    }
  }
});

Specify this action on component call.

{{some-component transInComponent=(action "transInController")}}

AFTER v3.4.0 (August 27, 2018)

some-component.js

export default Component.extend({
  actions: {
      componentAction1() {
          this.transInComponent();
      }
  }
});

OR simpler in some-component.hbs

<button onclick={{@transInComponent}}>GO HOME</button>

BEFORE v3.4.0

Ember.component.sendAction

"Send Action" from component up to controller

export default Ember.Component.extend({
  actions: {
      componentAction1() {
          this.sendAction('transInComponent');
      }
  }
});
Ramil Gilfanov
  • 552
  • 1
  • 8
  • 12
  • I would further change this to include the option to decide where to transition to as an option, but this is the correct answer now with Ember. – al3xnull Aug 30 '17 at 18:51
4

A component is supposed to be isolated from its context, so while you could pass in a reference to the controller, that's probably outside the scope of what a component is for. You might want to just stick with using a view with its own controller instead. Check out Views Over Components - An Ember Refactoring Story.

From Ember.js, Sending Actions from Components to Your Application, there's discussion about sending actions from a component up the route hierarchy.

Leo Nikkilä
  • 1,547
  • 18
  • 29
aceofspades
  • 7,568
  • 1
  • 35
  • 48
3

A lot of things changed in Ember since the original post. So maybe today the best option would be to pass down to the component a route action that takes care of the transition (maybe using the fancy addon ember-cli-route-action.

Otherwise you can create an initializer with ember g initializer router and inside put in there a code like this one

export function initialize (application) {
   application.inject('route', 'router', 'router:main')
   application.inject('component', 'router', 'router:main') 
}

export default {
  name: 'router',
  initialize
}

This way you can access the router in your component with this.get('router') and, for instance, perform a transition

 this.get('router').transitionTo('images')
1

At component.HBS component file make a {{#link-to "routeDestinationYouWant" }}

For Example:

<section class="component">
{{#link-to "menu.shops.category.content" "param"}}
        <figure id="{{Id}}" class="list-block yellow-bg text-center" {{action "showList" "parameter"}}>
            <section class="list-block-icon white-text my-icons {{WebFont}}"></section>
            <figcaption class="list-block-title black-text">{{{Title}}}</figcaption>
        </figure>
          {{/link-to}}
</section>
menepet
  • 796
  • 13
  • 17
  • link-to component can't be applied to a click into simple span. I'm facing same problem here. How could I transit to another route from component action. – heat Apr 29 '16 at 21:21
  • Works for me :D. @heat I just use a normal `` and wrap a `{{#link-to 'route-name'}}{{/link-to}}` around the button, then use CSS to style my button to look like a text label or span, nice and simple. – Zhang Dec 03 '16 at 10:05
0

I've written this answer for another similar question.

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.

Link to question: Ember transitionToRoute cleanly in a component without sendAction

Link to answer: https://stackoverflow.com/a/41972854/2968465

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