找不到Backbone Marionette'itemViewContainer'

时间:2014-01-07 21:27:52

标签: javascript jquery backbone.js marionette

第一次使用Marionette,当我尝试渲染CompositeView时,我遇到了'itemViewContainer'属性的问题。

我已经让CompositeView在同一个应用程序中工作,但在这种情况下,我试图在用户点击按钮时呈现'PopupView'。在这个弹出窗口中,有一个由没有出现的CompositeView呈现的表。

这是用户可以打开弹出窗口的视图。这是CompositeView中的一个项目。

define([
    'marionette',
    'templates',
    'views/SectionPopupView'
], function(
    Marionette,
    templates,
    SectionPopupView
) {

  /** ClassListingRowView represents a row in the ClassListingView.
   *  Each Row is tied to a specific Course object that's passed in
   *  when the Row is instantiated in ClassListingView.
   *  this.model: Course model
   *  this.options.user: User model */
  return Marionette.ItemView.extend({
    template: templates.classListingRow,
    className: 'class-listing',
    popupView: null,

    ui: {
      'editBtn': 'a.edit-btn',
      'removeBtn': 'a.remove-btn',
      'popupContainer': 'div.popup-container'
    },

    events: {
      'click @ui.editBtn': 'editCourse',
      'click @ui.removeBtn': 'removeCourse'
    },

    /** Set the ID of this element to [UID]-listing. Also fetches data
     *  from the model. */
    // TODO: This calls render() twice... how do I make it better?
    initialize: function() {
      this.user = this.options.user;
      $(this.$el).attr('id', this.model.get('UID') + '-listing');

      var self = this;
      this.model.fetch({
        success: function() {
          self.render();
        }
      });
    },

    /** Spawns a popup with all sections that allows a user to choose
     *  which sections he/she does/doesn't want. */
    editCourse: function(e) {
      e.preventDefault();
      e.stopPropagation();

      var self = this;
      // Instantiate a view if it hasn't already been instantiated
      $(window.app.curtain).show();
      if (this.popupView == null) {
        this.popupView = new SectionPopupView({
          el: self.ui.popupContainer,
          model: self.model
        });
        this.popupView.render();
      } else {
        this.popupView.show();
      }
    },

    /** Removes this.course from the User's selectedCourse list.
     *  This will trigger an event which the ClassListingView should be
     *  listening for, and then this View will be discarded. */
    removeCourse: function(e) {
      e.preventDefault();
      e.stopPropagation();

      this.user.removeCourseFromSelected(this.model);
    }
  });
});

这是弹出窗口的视图:

define([
    'marionette',
    'templates',
    'views/PopupView',
    'views/SectionTableView',
    'jquery'
], function(
    Marionette,
    templates,
    PopupView,
    SectionTableView,
    $
) {

  /** A SectionPopupView is a View that represents a popup that shows all of
   *  the sections for a particular Course and allows a user to select
   *  which sections he wants to include and also to see more information
   *  about the course.
   *  model: Course */
  var SectionPopupView = PopupView.extend({
    template: templates.sectionPopup,
    sectionTable: null,

    ui: {
      'closeBtn': 'a.close',
      'tableContainer': 'div#table-container',
      'okBtn': 'a#submit'
    },

    events: {
      'click @ui.closeBtn': 'close',
      'click @ui.okBtn': 'continue'
    },

    /** Upon initialization, the View will have been instantiated with
     *  model: Course. A SectionListTableView must be instantiated upon
     *  init and populated with data from the model's sections attr. */
    initialize: function() {
      var self = this;
      this.on('render', function() {
        self.sectionTable.render();
      });
      this.sectionTable = new SectionTableView({
        el: self.ui.tableContainer,
        model: self.model
      });

      // this.sectionTable.render();
    },

    /** Hides the popup (and curtain). */
    show: function() {
      $(window.app.curtain).show();
      $(this.el).show();
    },

    /** Shows the popup (and curtain). */
    close: function(e) {
      e.preventDefault();
      e.stopPropagation();

      $(window.app.curtain).hide();
      $(this.el).hide();
    }
  });

  return SectionPopupView;
});

这里是表格的视图(sectionTable)

define([
    'marionette',
    'templates',
    'views/SectionTableRowView',
    'views/NoSectionsView',
    'jquery'
], function(
    Marionette,
    templates,
    SectionTableRowView,
    NoSectionsView,
    $
) {

  /**
   *  this.model = Course */
  return Marionette.CompositeView.extend({
    template: templates.sectionTable,
    itemView: SectionTableRowView,
    itemViewContainer: 'tbody',
    emptyView: NoSectionsView,

    initialize: function() {
      this.itemViewOptions = {
        user: this.model
      };
    }
  });
});

我在这里读到很多人都有这个问题,因为他们试图在DOM之前渲染视图,所以我将表格的渲染功能绑定到弹出窗口的渲染事件,但这也没有用。有帮助吗?

除此之外,我是否对MVC指南/最佳实践等做了错误的处理?我对我的代码没有100%的信心,所以反馈也会受到赞赏!感谢。

1 个答案:

答案 0 :(得分:0)

有几件事:

1)您的this.on("render"...代码需要通过正确的上下文(我相信这有效):

this.on("render", function() {
  this.sectionTable.render();
}, this);

这一点可以移动到此视图的onRender函数,这有助于清晰:

onRender: function() {
  this.sectionTable.render();
}

2)了解木偶在DOM周围使用的信号非常重要:

当该视图的onRender已在虚拟DOM中完全构建但在将其插入用户的(/ jQuery可访问的)DOM之前,

$el方法被调用

使用onShow调用

$el方法,以便该视图在DOM中成功访问,并且可以访问jQuery。

有一些onShow边缘情况可以出现,通常只有在深度嵌套布局时才会发生。如果你很好奇我写了here