开发者

Backbone.js: How to call methods on the collection within an object literal

I have the following backbone.js code. I'm using an object literal for organizing my code, which has left me with a question regarding the best way to proceed. The application (in its simplified form below) has a control panel (which can be shown or hidden) which is used to add new categories to a collection. (Question follows)

(function($){

    // ============================= NAMESPACE ========================================
var categoryManager = categoryManager || {};

    // ============================= APPLICATION =================================================

categoryManager.app = categoryManager.app || {

    /* Used to Initialise application*/
    init: function(){
        //this.addView = new this.addCategoryView({el: $("#add-new-category")})
        //this.collection = new this.categoryCollection();
        new this.addCategoryView({el: $("#add-new-category")})
        new this.categoryCollection();
    },

    categoryModel:  Backbone.Model.extend({
        name: null
    }),

    addCategoryView: Backbone.View.extend({

        events: {
            "click #add-new-category-button.add" : "showPanel",
            "click #add-new-category-button.cancel" : "hidePanel",
            "click #new-category-save-category" : "addCategory"
        },
        showPanel: function() {
            $('#add-new-category-button').toggleClass('add').toggleClass('cancel');
            $('#add-new-category-panel').slideDown('fast');
        },
        hidePanel: function() {
            $('#add-new-category-button').toggleClass('add').toggleClass('cancel');
            $('#add-new-category-panel').stop().slideUp('fast');
        },
        addCategory: function() {
            //categoryManager.app.collection.create({
            categoryManager.app.categoryCollection.create({ // My Problem is with this line
                name: $('#name').val()
            });
        }
    }),

    categoryCollection: Backbone.Collection.extend({
        model: this.categoryModel,
        initialize: function () {

        }
    })
}
    // ============================= END APPLICATION =============================================

    /* init Backbone */

    categoryManager.app.init();

})(jQuery);

Now obviously the problem with the above, is that calling the addCategory function tries to call a function on an object which is uninitialized. I've worked round the problem (see commented out code) by calling the function instead on a object which is instantiated within the init function. My question is - is this the right thing to do? I detect a code smell. I feel that the contents of the object lit开发者_JS百科eral shouldn't rely on the object being created in order to be valid. the function addCategory in this instance wouldn't work unless the init function had been called on the parent first. Is there another pattern here that I should be using?

How else would I pass the contents of the 'create new category form' to the collection in order to be added (I'm using create because I want to automatically validate/create/persist the model and It seems like the easiest thing to do). I'm a rock bottom novice with backbone (this is my 'hello world')

Thanks


I think the main issue is you are treating categoryCollection as if it's an object. It's not really an object, but a constructor function. So first you need to create an instance, as you have discovered.

Then the addCategoryView needs some way of referencing the instance. It looks like you don't have a model associated with the view. I would suggest creating a model and storing the categoryCollection instance as a property of the model. Something like this (warning, untested code):

var model = new BackBone.Model({
    categories: new categoryManager.app.CategoryCollection()
});

var view = new categoryManager.app.AddCategoryView({
    el: $("#add-new-category"),
    model: model
});

Then you can just use this.model.categories from inside addCategoryView.

As an aside, a common Javascript convention is to capitalize the names of constructors. Calling the constructor CategoryCollection might make the code a little bit clearer.


You need to initialize collection before create a new instance of a model

addCategory: function() {
    var collection = categoryManager.app.categoryCollection;

    !collection.create && (collection = new collection);
    collection.create({
        name: $('#name').val()
    });
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜