Search code examples
javascriptbackbone.jsnestedmodels

Nested models of the same 'class' in the Backbone.js framework?


I'm new to Backbone.

Is it possible to define a Model in backbone which contains a list of Models of the same type? Example:

MyModel = Backbone.Model.extend({
  initialize: function() {
    nestedMyModels:new Array();
  },

  addMyModel: function(aModel) {
    // Code here would push() aModel onto array
  },

  render: function() {
     // Loop through array calling render() recursively
  }
});

I would then have a View which started a recursive call to render(). Example:

MyView = Backbone.View.extend({
  render:function() {
     this.model.render();
  }
});

Solution

  • 1 no arrays but Collections

    Always that you think in an Array of Models in Backbone think in a Collection.

    Now what you have to do is implement a Collection of MyModels and keep one instance of it in your MyModel instance.

    // code simplified and not tested
    MyModel = Backbone.Model.extend({
      initialize: function() {
        this.nestedMyModels: new MyModels();
      },
    
      addMyModel: function( model ) {
        this.nestedMyModels.add( model );
      }
    });
    
    MyModels = Backbone.Collection.extend({
      model: MyModel
    });
    

    2 use Views for render

    Always that you think in render think in a View.

    And the recommend way is that if you have a Collection and a Model better having a View for each one. This way the View of the Collection will call the View of the Model in an iteration:

    // code simplified and not tested
    MyModelView = Backbone.View.extend({
      render: function(){
        this.$el.html( model.get("name") );
        var view = new MyModelsView({ collection: this.model.nestedMyModels });
        this.$el.append( view.render.el );
    
        return this;
      }  
    });
    
    MyModelsView = Backbone.View.extend({
      render: function(){
        this.collection.each( function( model ){
          var view = new MyModelView({ model: model });
          this.$el.append( view.render.el );
        });
    
        return this;
      }
    });