17

What is the "appropriate" way in Ember to send a parameter from one route to another? For instance, I have two routes defined as such:

this.resource('activities', { path: '/activities/:on_date' }, function() {
    this.route('new');
});

when on the ActivitiesRoute the user is presented with a dropdown of possible activities. When they choose something it transitions to the ActivitiesNewRoute:

this.transitionToRoute('activities.new');

and I know there is a second parameter available in the transitionToRoute(route,model) method but it's meant for passing in a model and I'm assuming this shouldn't be repurposed for other parameter passing. In this case the dropdown choice is picking an Action model id and the model for ActivitiesNew is a Activity.

Here are my three guesses at ways that might work:

1) Make it a router parameter

I supposed I could change ActivitiesNew to include a "parameter" as part of the route:

this.route('new', { path: '/new/:my_parameter' });

I'm not sure I'd really like to have it becoming part of the URL path but if this was the prevailing convention then I'd live with that.

2) Get a handle, post transition

Immediately following the transitionToRoute call I could set a property of the new controller class. Not sure if the controller would be setup yet but I'm imagining something like:

this.transitionToRoute('activities.new');
this.get('target').controllerFor('activities.new').set('my_parameter', myValue);

3) Use model parameter

this.transitionToRoute('activities.new',myValue);

I suspect that this is a major no-no. I haven't looked into the Ember code to know if this could work but it seems against convention so this is my "bad option".

ken
  • 8,763
  • 11
  • 72
  • 133

5 Answers5

47

transitionTo & transitionToRoute return a "promise-like" object. The parameter this object is resolved with is the route, from which you can access controller and currentModel. So a nice clean way to pass information to a route to which you are transitioning is:

var my_param = ....;
this.transitionToRoute('activities.new').then(function(newRoute) {
  newRoute.currentModel.set('someProperty', my_param);
  //or
  newRoute.controller.set('someProperty', my_param);
});

EDIT/RANT:

note that in most cases, you do want to use needs, and bind things between controllers. However, there are certainly instances when you have things that depend on the logic of a route transition -- eg., controllerB has state X if we came to routeA from routeB, but state Y if we came from routeC. In that case, my answer is valuable.

The primary value of stack overflow to the development community is not the immediate answers you get to questions you post, but the massive ever growing wealth of googleable development knowledge. When you "infer" from a user's question that they "should" be doing something other than what they are asking how to do, you may be right (or you may be just incapable of imagining their particular circumstance), but if you answer only with your recommendation/rule/aphorism/cargo-cult-dictum instead of answering the ACTUAL QUESTION, you diminish the value of everybody else's google searches. If you want to tell someone to do something other than what they're asking, do it in a comment, or in a footnote to an answer to the actual question.

Michael Johnston
  • 5,298
  • 1
  • 29
  • 37
  • The ember way is still to use the "needs" approach for binding properties between routing controllers. Setting a property manually on a controller that depends on some other controller, won't bind the property. Plus, setting properties on models, outside of models definitions is bad practice. – Panagiotis Panagi Jun 08 '14 at 08:28
  • This answer was very helpful! I'm wondering if this is the proper way I might set a "success" message, by setting some success property to true during a transitionToRoute and displaying a success message conditionally. Thoughts? – Ruben Martinez Jr. Jun 09 '14 at 18:05
  • Hi,please tell me how can I get this value from the transited controller – Tanvir Sep 09 '14 at 08:19
6

You can use the needs API (Read about it here):

App.ActivitiesNewController = Ember.ObjectController.extend({
  needs: ['activities']

  // Bind the property you need
  actionTemplateBinding: 'controllers.activities.actionTemplate'
});

So what you actually need is to pass a parameter between controllers, which is exactly what needs is for. Plus, binding the property with needs you ensure it is in sync at all times, instead of relying on setupController being called.

Panagiotis Panagi
  • 9,927
  • 7
  • 55
  • 103
2

You could use query-params (http://guides.emberjs.com/v1.10.0/routing/query-params/), as follows:

this.transitionToRoute('activities.new', {queryParams: {my_param: 'my_value'});

In order to be able to receive my_param in the new controller, you would also need to define the following lines:

App.ActivitiesNewController = Ember.ObjectController.extend({
    queryParams: ['my_param'],
    my_param: ''
    ...
});

A drawback of this solution is that the value of my_param will be serialized in URL - so it would not be suitable for some sensitive information you may want to pass between routes.

chazkii
  • 1,300
  • 12
  • 21
TitoFHR
  • 87
  • 2
  • 8
0

I'll answer my question with what I've decided to go with for now but keep it open for a a few days to see if anyone comes back with a more experienced answer. My answer may very well be perfectly fine ... it works anyway.

I've gone with a variation of #2 from the question. The difference is that that rather than trying to set a property in the ActivitiesNew controller from Activities controller I do the the opposite:

In ActivitiesNewRoute:

App.ActivitiesNewRoute = Ember.Route.extend({
    model: function(params) {
        return this.store.createRecord('activity');
    },
    setupController: function(controller,model) {
        controller.set('actionTemplate', this.controllerFor('activities').get('actionTemplate'));
    }
});

Still interested in hearing from people if there's a better way of doing this.

ken
  • 8,763
  • 11
  • 72
  • 133
0

Transition to route with params and set model

yourAction:->
    model = 'your-model'
    route = 'your.path.to.toute'
    routeLoad = @transitionToRoute route,
        id: model.get 'id'
    routeLoad.then (route) ->
        route.set 'controller.model', model
    return
DenQ
  • 89
  • 1
  • 6