Undefined model prototype in Backbone Collection and Marionette CompositeView

笑着哭i 提交于 2019-12-23 07:46:07

问题


Trying to populate a Collection from a list of values, I am getting an error about the Collection's model's prototype being undefined. Looking at this question about a similar problem, I have checked that the Model is actually created before the collection is instanced, to the best of my ability.

The error is being thrown in one of the event handlers of the Marionette CompositeView that holds the Collection, after fetching the data from the server and trying to reset the collection with the list of values from the data which should be populated into it.

Note: Using Backbone 0.9.10

The Model

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

The Collection

MyCollection = Backbone.Collection.extend({
    model: MyItemModel
});

The CompositeView's relevant code

MyCompositeView = Backbone.Marionette.CompositeView.extend({

    initialize: function(options) {
        _.bindAll(this);
        this.model = new MyCompositeViewModel();
        this.collection = new MyCollection();
    },

    //This event handler gets properly fired and run.
    on_event: function() {
        var that = this;

        // The data comes through fine with this `fetch`
        this.model.fetch({success: function() {
            var collection_results= that.model.get("collection_results");

            // The error fires in this line
            that.collection.reset(collection_results);
            that.render();
        });
    }
})

The error

The error happens in the add function in Backbone, when doing a get for the model object, checking to see if it is a duplicate. The failing code is here:

// Get a model from the set by id.
get: function(obj) {
    if (obj == null) return void 0;

    // The error originates from this line
    this._idAttr || (this._idAttr = this.model.prototype.idAttribute);
    return this._byId[obj.id || obj.cid || obj[this._idAttr] || obj];
},

this._idAttr || (this._idAttr = this.model.prototype.idAttribute);

Here, the this.model.prototype.idAttribute fails because the prototype for the model is not defined.

Why is this happening, and how can it be fixed?

Thanks a lot!


回答1:


The reason is, in Babkbone 0.9.10, if you call collection.reset(models) without options, the models will be passed to collection.add() which strictly needs real models as argument.

But, in fact, the arguments you passed are not real models. They are just an array of hash attributes.

Two options to fix:

Option 1: Call the reset with a parse option

that.collection.reset(collection_results, {parse: true});

Then reset will parse the array of hashes and set them as model.

Option 2: Upgrade to latest version Backbone 1.1.0.

Here reset() no longer pass responsibility to add() but use set() smartly. This option is recommended. And you don't need options here.

that.collection.reset(collection_results)

Another point

May I suggest you not to define model in CompositeView? CompositeView is for collection, not model. Of course I understand the model here is just to hold and fetch some data, but it would be really confusing for the code to be read by another developer, as well as your own maintaining.

To get bootstrapped data, you can load the data at first request and use conventional way to put it into collection. http://backbonejs.org/#FAQ-bootstrap



来源:https://stackoverflow.com/questions/20709469/undefined-model-prototype-in-backbone-collection-and-marionette-compositeview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!