17
votes

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.

4

4 Answers

25
votes

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.

3
votes

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!
2
votes

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

1
votes

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.