3

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@test.com"};
        //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;
Edward Ellsworth
  • 455
  • 5
  • 12

3 Answers3

1

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.

  • I discovered that I could define my route as: this.resource('addcontact', {path: '/addcontact/:info'}); and this allowed me to pass the new object as a model through the transitionToRoute method. I don't know if this is proper, because I couldn't really find anything in the docs about it, but it worked. – Edward Ellsworth Jun 15 '15 at 21:41
  • Is it possible to pass without query parameters? – levi Nov 28 '17 at 12:37
0

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.

QuantumLicht
  • 2,103
  • 3
  • 23
  • 32
  • 1
    Well, since the data will be generated on the fly, it would not have an id yet, so how would I just pass the whole model through? – Edward Ellsworth Jun 15 '15 at 19:26
  • You don't need to change your Controller code, just your router. It should work. Have a look at the ember doc if you are unsure: http://emberjs.com/api/classes/Ember.Controller.html#method_transitionToRoute – QuantumLicht Jun 15 '15 at 19:37
  • @EdwardEllsworth Please don't forget to accept a solution so future users can know what works :) – QuantumLicht Jun 16 '15 at 02:47
0

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

Rick Smith
  • 9,031
  • 15
  • 81
  • 85