Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
107 views
in Technique[技术] by (71.8m points)

javascript - Backbone.js model with collection

I have 2 models and one collection. JobSummary is a model, JobSummaryList is a collection of JobSummary items, and then I have a JobSummarySnapshot model that contains a JobSummaryList:

JobSummary = Backbone.Model.extend({});

JobSummaryList = Backbone.Collection.extend({
    model: JobSummary
});

JobSummarySnapshot = Backbone.Model.extend({
    url: '/JobSummaryList',

    defaults: {
        pageNumber: 1,
        summaryList: new JobSummaryList()
    }
});

When I call fetch on the JobSummarySnapshot object, it gets everything... Except when I move through the summaryList collection they are all of type object and not JobSummary.

I suppose this makes sense since other than the defaults object, it doesn't know that the summaryList should be of type JobSummaryList. I can go through each item and convert it to a JobSummary object, but I was hoping there was a way to do it without having to do it manually.

Here's my test code (working jsfiddle here):

var returnData = {
    pageNumber: 3,
    summaryList: [
        {
        id: 5,
        name: 'name1'},
    {
        id: 6,
        name: 'name2'}
    ]
}; 

var fakeserver = sinon.fakeServer.create();
fakeserver.respondWith('GET', '/JobSummaryList', [200,
{
    'Content-Type': 'application/json'},
                                JSON.stringify(returnData)]);

var callback = sinon.spy();


var summarySnapshot = new JobSummarySnapshot();
summarySnapshot.bind('change', callback);

summarySnapshot.fetch();
fakeserver.respond();

var theReturnedList = callback.getCall(0).args[0].attributes.summaryList;

_.each(theReturnedList, function(item) {
    console.log('Original Item: ');
    console.log(item instanceof JobSummary); // IS FALSE
    var convertedItem = new JobSummary(item);
    console.log('converted item: ');
    console.log(convertedItem instanceof JobSummary); // IS TRUE
});

UPDATE: It occurred to me that I could override the parse function and set it that way... I have this now:

JobSummarySnapshot = Backbone.Model.extend({
    url: '/JobSummaryList',

    defaults: {
        pageNumber: 1,
        summaryList: new JobSummaryList()
    },

    parse: function(response) {
        this.set({pageNumber: response.pageNumber});

        var summaryList = new JobSummaryList();
        summaryList.add(response.summaryList);

        this.set({summaryList: summaryList});
    }
});

This works so far. Leaving the question open in case someone has comment on it....

question from:https://stackoverflow.com/questions/7140741/backbone-js-model-with-collection

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your parse() function shouldn't set() anything, its a better practice to just return the attributes, Backbone will take care of setting it. e.g.

parse: function(response) {
    response.summaryList = new JobSummaryList(response.summaryList);
    return response;
}

Whatever you return from parse() is passed to set().

Not returning anything (which is like returning undefined) is the same as calling set(undefined), which could cause it not to pass validation, or some other unexpected results if your custom validate()/set() methods expects to get an object. If your validation or set() method fails because of that, the options.success callback passed to Backbone.Model#fetch() won't be called.

Also, to make this more generic, so that set()ing to a plain object from other places (and not only from the server response) also effects it, you might want to override set() instead:

set: function(attributes, options) {
    if (attributes.summaryList !== undefined && !(attributes.summaryList instanceof JobSummaryList)) {
        attributes.summaryList = new JobSummaryList(attributes.summaryList);
    }
    return Backbone.Model.prototype.set.call(this, attributes, options);
}

You might also find Backbone-relational interesting - it makes it much easier to deal with collections/models nested inside models.

edit I forgot to return from the set() method, the code is now updated


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...