ChatGPT解决这个技术问题 Extra ChatGPT

How do I fetch a single model in Backbone?

I have a Clock model in Backbone:

var Clock = Backbone.Model.extend({});

I'm trying to get an instance of that that has the latest information from /clocks/123. Some things I've tried:

a "class"-level method

Clock.fetch(123)
// TypeError: Object function (){ ... } has no method 'fetch'

creating an instance and then calling fetch on it:

c = new Clock({id: 123})
c.fetch()
// Error: A 'url' property or function must be specified

a collection

I tried creating an AllClocks collection resource (even though I have no use for such a thing on the page):

var AllClocks = Backbone.Collection.extend({
  model: Clock,
  url: '/clocks/'
});
var allClocks = new AllClocks();
allClocks.fetch(123);
// returns everything from /clocks/

How do I just get one API-backed Clock?

IMHO it belongs to the collection. Something like Collection#fetchOne(id, callback).

H
Hernan S.

Try specifying urlRoot in the model:

From the docs:

var Book = Backbone.Model.extend({urlRoot : '/books'});
var solaris = new Book({id: "1083-lem-solaris"});
solaris.fetch();

This is good, but sometimes you don't want to reinstantiate the model. If you want to fetch a specific item against the same model, you can do a silent set: currentBook.set('id', 13423, {silent:true}). This works too, but I'm not sure why: currentBook.id = 13423
@SimplGy that works because model.id is essentially synonymous with model.attributes.id. If you call model.set('id'), Backbone sets model.id to whatever you specified. And model.id is what gets used when creating the model-specific URL.
A
Andrew De Andrade

Your second approach is the approach I have used. Try adding the following to your Clock model:

url : function() {
  var base = 'clocks';
  if (this.isNew()) return base;
  return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + this.id;
},

This approach assumes that you have implemented controllers with the hashbang in your URL like so, http://www.mydomain.com/#clocks/123 , but it should work even if you haven't yet.


There is a way to avoid this as explained in Backbone Model documentation documentcloud.github.com/backbone/#Model-url
@makevoid your I could not make work the example you provide in coffee script or the one in the documentation, the Andrew example works, could you provide and example with foo.url(), it always tell me that there's no function url.
@makevoid it seems the method you are referring to only works if the model has been created in a collection. Notice the collection in [collection.url]/[id].
@makevoid can you please provide a working link? unfortunately, this one is broken for now
here's the working link (they moved the doc! wow, 5 years passed, geez): backbonejs.org/#Model-url - @StevenDevijver is correct
m
makevoid

I personally recommend, following the Model#url method documentation

model = new Model(id: 1)
view = new View(model: model) 
collection = new Collection([model])
model.fetch()

in your collection remember to add the collection url:

url: "/models"

and in your View's initialize function do:

this.model.bind("change", this.render)

this way backbone will do an ajax request using this url:

"/models/1"

your model will be updated and the view rendered, without modifying Collection#url or Model#urlRoot

note: sorry this example came out in coffee script, but you can easily translate it to js adding var statements


Apparently this doesn't work. Don't even makes a call to the server when calling fetch in the model (nor the collection)
This looks fine, but the collection line looks awkward in cases when we don't really need the collection.
i couldn't get this to work: this.model.get('field'). Looks like the model is is created sub object
this.model.bind("change", this.render, this) worked well for me
@UlysseBN yes (was year 2011), you can add var statements, {} inside the ()'s for the passed objects and optional ; ad the end of the lines
A
Ankit Garg
var Person = Backbone.Model.extend({urlRoot : '/person/details'});
var myName = new Person({id: "12345"});
myName.fetch();

As a result you make a Ajax request on the

URL http://[domainName]/person/details/id 

and you have the JSON response back.

Enjoiiii !!!


this is the same solution as @Hernan
4
4m1r

...and do this if you don't want the trailing slash on the model urlRoot:

    url : function() {                        
        return this.urlRoot + this.id;
    },

s
ssobczak

You probably should be accessing the object trough a collection and keeping it in the collection all the time. This is how to do it:

var AllClocks = Backbone.Collection.extend({
  model: Clock,
  url: '/clocks/'
});

var allClocks = new AllClocks();
my_clock = allClocks.add({id: 123});
my_clock.fetch()

You don't know that. Maybe all he requires is one Clock. Suppose I want to present a client with a single Model of a User record? Should he have access to a Collection of all Users too? Sometimes folk just need some advice while trying to keep their usecase private. Just answer.
A
Araell

I want to use RESTful url,but I couldn't understand why 'postId' can't be added to base url.

var PostModel = Backbone.Model.extend({
    urlRoot: 'getBlogPost',
    defaults: {
        postTitle: "defaultTitle",
        postTime: "1970-01-01",
        postContent: "defaultContent",
        postAuthor: "anonymous"
    }
});

var post = new PostModel({
            postId: 1
        });
alert(post.url());

Then I know only after I set 'idAttribute' as 'postId' in Model can I get the right url. like this:

var PostModel = Backbone.Model.extend({
    idAttribute: 'postId',
    urlRoot: 'getBlogPost',
    defaults: {
        postTitle: "defaultTitle",
        postTime: "1970-01-01",
        postContent: "defaultContent",
        postAuthor: "anonymous"
    }
});