Ember passing a model to transitionToRoute

6.9k views Asked by At

I'm using Ember-cli with ember 1.11

I'm trying to use the transitionToRoute method in a controller to transition to a route and feed it a dynamically generated object as the model.

Here's my controller:

import Ember from 'ember';

export default Ember.Controller.extend({
  actions: {      
      launch_scanner: function(){
        console.log('launch_scanner');
        var model = {name: "Edward", phone: "123", email: "[email protected]"};
        //the final app will pull the model variable from a QR scanner

        this.transitionToRoute('addcontact', model);
     }
  }      
});

When I trigger this action, the transitionToRoute method causes this error:

Uncaught Error: More context objects were passed than there are dynamic segments for the route: addcontact

If I leave out the model parameter, it transitions to the addcontact route just fine. What am I doing wrong?

Here is my router file:

import Ember from 'ember';
import config from './config/environment';

var Router = Ember.Router.extend({
  location: config.locationType
});

Router.map(function() {
  this.route('home', {path: '/'});
  this.resource('addcontact', {path: '/addcontact'});
});

export default Router;
3

There are 3 answers

2
AudioBubble On BEST ANSWER

You are dealing with a classic problem occurring in many Ember applications which is how to handle "new"/"create" situations.

You cannot define a route such as

this.route('addcontact', { path: /addcontact/:thing_id }

because the the new contact doesn't have an id, and won't until it is persisted to the server, at which point it won't be new any more.

Yet there is some point in your application, in your case I suppose on the "home" page, where the user pressed a "New Contact" button, and it may have useful information about what to create or how to create it, and might even want to create the object right there using this.store.createRecord--yet how does one pass that information, or the new record, to the addcontacdt route, which can have no dynamic segment?

Some ideas include:

  1. Create the new contact in your home route or whatever, and store it in the controller. Then, in the model hook of the new route, retrieve it using this.controllerFor('home').get('newContact').

  2. Pass necessary parameters for creating the new object, if any, to the addcontact route as query parameters, using transitionTo('newcontact', queryParameters). Then, in the model hook, create the new object using this.store.createRecord('contact', transition.queryParameters) or something equivalent.

3
QuantumLicht On

That's normal, because you don't have any dynamic segment in your addContact route. You should change your router to

Router.map(function() {
  this.route('home', {path: '/'});
  this.resource('addcontact', {path: '/addcontact/:id'});
});

Now you could pass the model Id instead of the whole model to trigger the model hook. Alternatively you can pass the whole model, but it will not trigger the model hook. Although you can still modify your model in the afterModel hook.

0
Christian Stengel On

If you want to navigate to a Subroute for an unsaved Record you have 2 Options

Either save your model before transitioning to the route

model.save().then(function(result){
   self.transitionToRoute('route',result.id)
});

or generate an id for the model in createRecord if you don't want to save the model (maybe the user can cancel and you don't want to handle the delete)

A basic function for id creating with low potential of identical ids would be:

generateIdForRecord: function() {
    var d = new Date().getTime();
    var uuid = 'xxxxyyyxxxxxxxxyyxyxxxyyy'.replace(/[xy]/g, function(c){
        var r = (d + Math.random() * 16) % 16 | 0;
        d = Math.floor(d / 16);
        return (c === 'x' ? r : (r & 0x7 | 0x8)).toString(16);
    });
    return uuid;
}

Using this approach a not yet saved model has an id to transition to, just think about handling the transitions from that route since the current id is no longer valid after saving the model (model gets real id from server in response).