Working with Marionette for the first time and I've run into an issue with the 'itemViewContainer' attribute when I try and render a CompositeView.
I've gotten the CompositeView to work in the same app, but in this case I'm trying to render a 'PopupView' when the user clicks on a button. Within this popup, there's a table that's rendered by a CompositeView that's not appearing.
Here's the View in which the user can open the popup. This is an item in a 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);
}
});
});
Here's the View of the popup:
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;
});
and here's the View for the table (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
};
}
});
});
I read on here that a lot of people had this issue because they were trying to render the view before it was in the DOM, so I binded the table's render function to the popup's render event, but that didn't work either. Any help?
Apart from that, am I doing anything incorrectly with regards to MVC guidelines/best practices/etc? I'm not 100% confident in my code, so feedback would be appreciated as well! Thanks.