动态设置子视图$ el并激活Backbone事件

时间:2014-06-24 16:54:56

标签: javascript backbone.js backbone-views backbone-events

我有一个父视图(和关联的模型),有几个子视图具有相同的关联模型。父视图是从HTML静态定义的。这些活动工作正常。

子视图是动态创建的,并且最终不同,但具有一些类似的初始结构。 #id将彼此不同(使用视图ID号),以便我们可以知道用户与哪个进行了交互。我在阅读中尝试了以下内容:

  • 在创建View时(在JS的末尾)添加el声明
  • 静态定义它,然后尝试更新它。
  • 使用_.ensureElement()
  • init()
  • 中设置el

但我似乎无法通过小提琴的观点来获得它。

Fiddle

JS:父母

  //The view for our measure
  parentModule.View = Backbone.View.extend({
    //
    //This one is static, so I can set it directly, no problem, the events are working
    //
    el: $('#measure-container'),
    events: {
        'click .test': 'test'
    },
    test: function(){
      alert('test');
    },
    initialize: function() {
      this.template = _.template($('#instrument-template').html());
    },
    render: function(){
      $(this.el).append(this.template(this.model.toJSON()));
      return this;
    }
  });

  return parentModule;
});

JS:孩子

  // THe child views are dynamic, so how do I set their id's dynamicall and still get the click events to fire?
  //
  childModule.View = Backbone.View.extend({
    //
    // Do I set the el here statically then override?
    //
    events: {
      'click .remove-rep' : 'removeRepresentation',
      'click .toggle-rep' : 'toggleRepType',
      'click .sAlert': 'showAlert'
    },
    initialize: function(options) {
      //
      //Do I set the el here using ensure_element?
      //
      this.model=options.model;
    },
    render: function(){
      //
      // Do I Set it here when it renders?
      //

      this.template = _.template($('#rep-template').html());
      $('#measure-rep-container').append(this.template());
      return this;
    },
    showAlert: function() {
      alert("This is an alert!");
    }
  });

JS:Instantiation

define( "app", ["jquery", "backbone", "parentModule", "childModule"], function($, Backbone, ParentModule, ChildModule) {    
  var app = {};
    app.model = new ParentModule.Model({ name: "Snare", numOfBeats: 4 });
    app.view = new ParentModule.View({ model: app.model });
    app.view.render();

    app.firstRepChildModel = new ChildModule.Model({ id: 1, type: 'circle', parentModel: app.model });
    // 
    // Do I add the el as a parameter when creating the view?
    // 
    app.firstRepChildView = new ChildModule.View({ el:'#rep'+app.firstRepChildModel.get('id'), model: app.firstRepChildModel });
    app.firstRepChildView.render();

    app.secondRepChildModel = new ChildModule.Model({ id: 2, type: 'line', parentModel: app.model });
    // 
    // Do I add the el as a parameter when creating the view?
    // 
    app.secondRepChildView = new ChildModule.View({ el:'#rep'+app.secondRepChildModel.id, model: app.secondRepChildModel });
    app.secondRepChildView.render();
  return app;
});

HTML:

<h3>Measure View</h3>
    <div id="measure-container">
    </div>

<!-- Templates -->
<script type="text/template" id="instrument-template">
  <div class="instrument">
      I am an instrument. My name is <%=name%>. <br/>
      Here are my children repViews: <br/>
      <div id="measure-rep-container">
        <div class="btn btn-primary test">Add a rep</div>
      </div>
  </div>
</script>

<script type="text/template" id="rep-template">
  <div class="rep" id="rep<%=this.model.id%>">
      I am a repView <br/>
      My ID is 'rep<%=this.model.id%>' <br/>
      My el is '<%=this.$el.selector%>'<br/>
      My type is '<%=this.model.type%>' <br/>
      I have this many beats '<%=this.model.numOfBeats%>' <br/>
      <div class="beatContainer"></div>
      <div class="btn btn-danger remove-rep" id="">Remove this rep</div>
      <div class="btn btn-primary toggle-rep" id="">Toggle rep type</div>
      <div class="btn sAlert">Show Alert</div>
  </div>
</script>

1 个答案:

答案 0 :(得分:1)

每个视图都有关联的el,无论您是否直接设置,如果您没有设置它,那么el只是一个空div。

在您的代码中,您不能修改您的子视图el或将其附加到DOM

尝试以下

render: function(){

  this.template = _.template($('#rep-template').html());
  //this sets the content of the el, however it still isn't attached to the DOM
  this.$el.html(this.template()); 
  $('#measure-rep-container').append(this.el);
  return this;
},

更新了fiddle

作为一个单独的点,如果您要多次重复使用相同的模板,您可能只想编译一次,例如

childModule.View = Backbone.View.extend({

events: {
  'click .remove-rep' : 'removeRepresentation',
  'click .toggle-rep' : 'toggleRepType',
  'click .sAlert': 'showAlert'
},

//get's called once regardless of how many child views you have
template: _.template($('#rep-template').html()), 

render: function(){
  this.$el.html(this.template()); 
  $('#measure-rep-container').append(this.el);
  return this;
},