17

Say I have a route setup:

'photos/:id' : 'showPhoto'

and somebody shares the url: www.mysite.com/photos/12345 with a friend.

When their friend clicks on the shared link, showPhoto gets called back with 12345 passed as the id. I cant figure out how to fetch the model from the server, because even when setting its id property and calling fetch(), backbone thinks that the model isNew and so the ajax request url is just /photos instead of /photos/12345:

showPhoto: (id) ->
  photo = new models.Photo _id:id
  photo.fetch #does a GET to /photos, I would have expected it to request /photos/12345
    success: () ->
      render photo view etc...

Photo = Backbone.Model.extend
  idAttribute: '_id'
  urlRoot: '/photos'

The model Photo is usually part of a collection, but in this scenario someone is visiting the site directly and only expects to see data for one photo, so the collection is not instantiated in this state of the app.

Is the solution to load the entire collection of photos and then use collection.getById(id)? This just seems way too inefficient when I just want to load the properties for one model.

cjroebuck
  • 2,273
  • 4
  • 30
  • 46

4 Answers4

25

if you don't have the model as part of a collection, you have to tell the model the full url manually. it won't auto-append the id to the urlRoot that you've specified. you can specify a function as the urlRoot to do this:

Photo = Backbone.Model.extend({
  urlRoot: function(){
    if (this.isNew()){
      return "/photos";
    } else {
      return "/photos/" + this.id;
    }
  }
});

Backbone uses the id of the model to determine if it's new or not, so once you set that, this code should work correctly. if it doesn't, you could always check for an id in the if-statement instead of checking isNew.

Derick Bailey
  • 72,004
  • 22
  • 206
  • 219
  • Derick, how did you come to learn so much about Backbone? I haven't found any definitive guide. I read Addy Osmani's Fundamentals and Recipes With Backbone, as well as countless blogs including yours. You seem to have a much deeper understanding than most. Where did you pick it up? – AndrewHenderson Jan 28 '13 at 08:44
  • 10
    Trial and error, reading the Backbone source code, reading everything I can about it, learning as much as I can about JavaScript... but mostly trying to teach other people. Teaching others forces you to dig deep and really understand what's going on. :) – Derick Bailey Jan 28 '13 at 12:54
  • 1
    This seems to be a dated answer as Backbone's APIs have improved. Can we improve on this response? – sankargorthi Oct 08 '13 at 23:09
3

You do not need to tell backbone whether or not to append the id the url. Per the documentation: http://backbonejs.org/#Model-fetch, you may simply set the urlRoot to the equivalent of the url in a collection.

Backbone will automatically append the desired id to the url, provided you use one of the following methods:

model.set("id", 5); //After initialized
model = new Backbone.Model({id: 5}); //New model

If you manually set the id in the attributes hash or directly on the model, backbone won't be aware of it.

model.id = 5; //Don't do this!
Alan
  • 213
  • 1
  • 4
2

there's already a similar question: "How do I fetch a single model in Backbone?"

my answer there should work for you (and it's in coffeescript)

also remember to check Backbone Model#url documentation, it's all explained there

Community
  • 1
  • 1
makevoid
  • 3,276
  • 2
  • 33
  • 29
1

I would bootstrap the collection (by rendering the following to the page) with just one model in it like this:

photos = new PhotoCollection();
photos.reset([ @Html.ToJson(Model) ]);

Note that the server side code that I use is ASP.Net MVC so use something specific to your server side architecture. Also note that the square brackets are important as they take your singular model and wrap it in an array.

Hope that's helpful.

timDunham
  • 3,318
  • 23
  • 24