François Richard François Richard - 22 days ago 7
Javascript Question

Feed backbone collection with multiple different model classes

I have several models which have their own url/api they can fetch.

I would like to keep them in a collection.


  • does it sound like a good idea?

  • how would you fetch them? (I'm thinking just to get the model I want to update from the collection then fetch it)



Let me know what you think, if you have any theoretical reading/advise.

Answer

A collection can contain any raw objects or any models derived from a Backbone.Model. Fetching a collection makes sense only if you have an API endpoint which returns an array of objects.

If you want to fetch a specific model, you can keep a reference to it, or just get it inside your collection, and then call fetch on it.

It can cause problems when you have id collisions, where identical ids are considered the same model and are merged together.

var book = new Book({ id: 1, title: "My Book" }),
    note = new Note({ id: 1, title: "note test" });

var collection = new Backbone.Collection([book, note]);
console.log(collection.length); // 1

Ways to avoid id collisions:

  • don't use ids for these models if possible, Backbone will use their cid.
  • use GUIDs.
  • make a custom id attribute composed of identifying data, like prepending the type attribute. (book1, note1).

A way to make a multi model collection is to use the model property as a function. Though it doesn't prevent id collision by default.

var BooksAndNotes = Backbone.Collection.extend({

    /**
     * Different models based on the 'type' attribute.
     * @param {Object} attrs   currently added model data
     * @param {Object} options
     * @param {Backbone.Model} subclass dependant of the 'type' attribute.
     */
    model: function ModelFactory(attrs, options) {
        switch (attrs.type) {
            case "book":
                return new Book(attrs, options);
            case "note":
                return new MTextSession(attrs, options);
            default:
                return new Backbone.Model(attrs, options);
        }
    },
    // fixes this.model.prototype.idAttribute and avoids duplicates
    modelId: function(attrs) {
        return attrs.id;
    },
});

var collection = new BooksAndNotes([{
    title: "My Book",
    type: 'book'
}, {
    title: "note test",
    type: 'note'
}]);

See similar questions about multiple models in a collection: