al3xnull
al3xnull

Reputation: 866

transitionToRoute('route') From Inside Component

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
  ...

Upvotes: 17

Views: 11804

Answers (6)

Ramil Gilfanov
Ramil Gilfanov

Reputation: 602

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');
      }
  }
});

Upvotes: 8

Alessio Calafiore
Alessio Calafiore

Reputation: 91

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')

Upvotes: 3

Jayant Bhawal
Jayant Bhawal

Reputation: 2204

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

Upvotes: 0

menepet
menepet

Reputation: 882

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>

Upvotes: 1

aceofspades
aceofspades

Reputation: 7586

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.

Upvotes: 4

chopper
chopper

Reputation: 6709

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')
  ...

Upvotes: 9

Related Questions