2

I want to have this thing as a result:

<div id='indicators'>
    <ul> group 1      
        <li>indicator 1</li>
        <li>indicator 2</li>        
    </ul>
    <ul> group 2      
        <li>indicator 1</li>
        <li>indicator 2</li>        
    </ul>
</div>

I have the Indicator model and view:

var IndicatorModel = Backbone.Model.extend({
  defaults: {
    name: "unset"
  }
});

var IndicatorView = Backbone.View.extend({
  tagName: 'li',
  className: 'indicator',
  initialize: function(options){
    _.extend(this, _.pick(options, "controller"));
    this.model.on('change', this.render, this);
  },
  render: function(){
    this.$el.html(this.model.get('name'));
    return this; // enable chained calls
  }
});

The IndicatorList model and view:

var IndicatorListModel = Backbone.Collection.extend({
  model:IndicatorModel,
  name: "unset"
});

var IndicatorListView = Backbone.View.extend({
  tagName: 'ul',
  className: 'indicatorList',
  initialize: function(options){
    _.extend(this, _.pick(options, "controller"));
    this.model.on('change', this.render, this);
  },
  render: function() {
    this.$el.html(this.model.name);
    var self = this ;

    this.model.each(function(indicatorModel,index){
      var indicatorView = new IndicatorView({model:indicatorModel});
      self.$el.append(indicatorView.render().$el);
    });

    return this ;
  }
});

And the IndicatorGroup model, view, and template:

var IndicatorGroupModel = Backbone.Collection.extend({
  model:IndicatorListModel
});

var IndicatorGroupView = Backbone.View.extend({
  el: "#container",
  template: _.template($("#indicatorGroupTemplate").html()),
  initialize: function(options){
    _.extend(this, _.pick(options, "controller"));
    this.model.on('change', this.render, this);
  },
  render: function() {
    this.$el.html(this.template());
    this.model.each(function(indicatorListModel,index){
      var indicatorListView = new IndicatorListView({model:indicatorListModel});
      $("#indicatorGroup").append(indicatorListView.render().$el);

    });

    return this ;
  }
});

  <!-- Indicators Group Templates -->
  <script type="text/template" id="indicatorGroupTemplate">
    <h1> Indicateurs </h1>
    <div id="indicatorGroup"></div>
  </script>

Here is the way I test it:

var indicatorModel1 = new IndicatorModel({name:"indicateur 1 (groupe 1)"});
var indicatorModel2 = new IndicatorModel({name:"indicateur 2 (groupe 1)"});
var indicatorModel3 = new IndicatorModel({name:"indicateur 3 (groupe 2)"});
var indicatorModel4 = new IndicatorModel({name:"indicateur 4 (groupe 2)"});
// --- Indicator List Models
var indicatorListModel1 = new IndicatorListModel([indicatorModel1,indicatorModel2]);
indicatorListModel1.name="groupe 1";
var indicatorListModel2 = new IndicatorListModel([indicatorModel3,indicatorModel4]);
indicatorListModel2.name="groupe 2";
// --- Indicator Group Models
var indicatorGroupModel = new IndicatorGroupModel([indicatorListModel1,indicatorListModel2]);
// --- View
var indicatorGroupView = new IndicatorGroupView({model:indicatorGroupModel});
indicatorGroupView.render()

It gives me this

<div id="indicatorGroup">
   <ul class="indicatorList">
    unset<li class="indicator">groupe 1</li>
    </ul>
    <ul class="indicatorList">
    unset<li class="indicator">groupe 2</li>
    </ul>
</div>

Whereas when I test directly in the console with this, it works correctly:

var indicatorListView1 = new IndicatorListView({model:indicatorListModel1});
$("#container").append(indicatorListView1.render().$el);
<ul> group 1      
    <li>indicator 1</li>
    <li>indicator 2</li>        
</ul>

I don't understand, for me it is the same thing. Why?

Braiam
  • 1
  • 11
  • 47
  • 78

1 Answers1

1

You've set a 'collection' (IndicatorListModel) as a 'model' of another 'collection' (IndicatorGroupModel). Backbone can sometimes do strange things when you try to make a collection of collections. Instead, make IndicatorListModel extend Backbone's model class and make one of the attributes of IndicatorListModel (perhaps call it 'list') a collection of IndicatorModel models. At every level of the chain, you should have a model, with an attribute mapped to a collection of the models below it. You should never have a direct 'collection of collections.'

Community
  • 1
  • 1
Michael.Lumley
  • 2,345
  • 2
  • 31
  • 53