In latest Ember, how do you link to a route with just the id/name of a model, rather than providing all of its attributes in the linking page?
Asked Answered
M

1

15

I ran into a problem when converting from Ember 1.0-pre2 to latest master (43354a98) and the new router, namely--

If I have a route which loads just the name and ID for a bunch of records, and tries to link each of those records to another route which should display the full model, when I arrive at the new route, the new model is never loaded, and name and ID are the only attributes that are available.

Example code:

App.Router.map(function() {
  this.route("index");
  this.resource("birds");
  this.resource("bird", {
    path: "/birds/:bird_id"
  });
});

App.BirdsController = Ember.ArrayController.extend({
  birds: [
    {
      name: "Pigeon",
      id: "b.15"
    }, {
      name: "Chicken",
      id: "b.133"
    }, {
      name: "Turkey",
      id: "b.126"
    }, {
      name: "Ostrich",
      id: "b.4"
    }, {
      name: "Barn Owl",
      id: "b.47"
    }
  ]
});

App.BirdRoute = Ember.Route.extend({
  model: function(params) {
    return App.Bird.find(params.bird_id);
  }
});

{{#each bird in birds}}
  <li>{{#linkTo "bird" bird}}{{bird.name}}{{/linkTo}}</li>
{{/each}}

where App.Bird.find() runs some XHR's to build up an Ember.Object from a set of remote API's (not using ember-data). The list of birds is hardcoded into the controller just for this example, to simplify the issue; in my real application, the list is coming from a remote API.

The behavior I'm seeing is that if you start on /birds and click one of the links, the router transitions to 'bird' and you arrive on /#/birds/b.5, but App.Bird.find() is never called, and the only data I have on the page are "name" and "id". However, if you then reload the page, it does call App.Bird.find() and properly builds up and displays the model.

Is there some way to force deserialization from the ID in the URL, or to just pass an ID to linkTo rather than an object that it will assume is complete? I had an analogous implementation working fine with the old router.

Misunderstanding answered 16/1, 2013 at 20:46 Comment(2)
I think this might have something to do with this issue: github.com/emberjs/ember.js/pull/1758 Have you tried with a version of ember that includes the referenced commit that fixes the issue: github.com/emberjs/ember.js/commit/…Jens
Yeah, unfortunately the version I'm using contains that commit (d269fa3).Misunderstanding
J
19

It seems like the model hook for App.BirdRoute never gets called when navigating using {{#linkTo}}... maybe this is because using {{#linkTo}} you are passing an object to the route from the birds route and ember doesn't think you should need to call model since it thinks the id has already been deserialized into an object. This seems to make sense since model gets called when you reload the page.

I used the setupController hook to call your App.Bird.find() method and pass that result into the controller. This gets called by either a direct URL or through a {{#linkTo}} click. If called by the {{#linkTo}} helper link setupController the model parameter will be the bird object passed with the {{#linkTo}} helper. If called directly from the URL the returned value from the model hook will be passed into setupController as the model parameter.

Here is a JSFiddle example

example with accessible URL

App.BirdRoute = Ember.Route.extend({
  model: function(params) {
    return {id: params.bird_id};
  },
  setupController: function(controller, model) {
    var bird_model = App.BirdTest.find(model.id);
    controller.set("content", bird_model);
  }
});
Jens answered 17/1, 2013 at 1:1 Comment(7)
Thanks! I got hung up on trying to make it work in the model hook, which, as you say, doesn't even get called in this case.Misunderstanding
+1 this works like a charm and doesn't even require to make a relations on objects. Though at the same time this is quite weird and I'm wondering is this the right behaviour? or should there be a relationships set between the models?Benediction
Thx for this answer. I have a wierd problem, though. Instead of /birds/"id" i get /birds/[object Object]. Can anybody tell me what's wrong?Nies
@Nies Did you ever work that out? I'm having the same difficulty.Revolve
@Revolve take a look at the serialize hook for a route: emberjs.com/api/classes/Ember.Route.html#method_serializeJens
By the way, if you need .get(), you do model: -> Em.object.create id: params.bird_idDerryberry
@Revolve It is a while ago that I touch the code. If I remember right it had to do how the link path looks like.Nies

© 2022 - 2024 — McMap. All rights reserved.