Why won't my Marionette CollectionView work with an empty collection?
I'm trying to render a CollectionView within a CompositeView (it's a list of tasks within each item of a list of projects). Everything works fine until I pass an empty collection into the CollectionView. The collection is allowed to be empty; a project can easily have no tasks assigned to it.
The error shown by Chrome is
Uncaught TypeError: Object [object Object] has no method 'on'
The collection of projects passed in is a valid Backbone.Collection
, as are the task lists returned by the filter methods of TasksCollection
, which is why I can't work out why the error above is shown.
Marionette's CollectionView can accept an empty collection (it has an emptyView
property), so why is it giving an error when one is passed in? I assume it's trying to bind events to the collection which should "just work" - it's only the models that are absent.
My tasks collection looks like this:
var TasksCollection = Backbone.Collection.extend({
model: TaskModel,
byProject: function(projectId) {
var matches = this.filter(function(task) {
return task.get('projectId') == projectId;
}, this);
return new TasksCollection (matches);
},
complete: function(state) {
return new TasksCollection (this.where({ complete: state }));
}
});
My views look like this:
// Single task item
var TasksListView = Marionette.CollectionView.extend({
tagName: 'ul',
className: 'tasks nav nav-stacked nav-pills',
itemView: Minuteboy.views.TaskItem,
emptyView: Templates['partials/tasks-empty']
});
// Project item (should probably be a Layout or CompositeView)
var DashboardProject = Marionette.ItemView.extend({
tagName: 'article',
template: Templates['partials/dashboard-project'],
initialize: function() {
this.on('render', function() {
var tasks = AllProjectTasks.byProject(this.model.get('id')).complete(false);
this.$el.find('.tasks-wrapper').html(new TasksListView({
collection: tasks
}).render().el);
});
}
});
// Containing view with page title and container for projects list
var DashboardPage = Marionette.CompositeView.extend({
template: Templates['pages/dashboard'],
itemView: DashboardProject,
itemViewContainer: '#content'
});
Finally, I instantiate the page view like this:
var page = new DashboardPage({
collection: // A valid Backbone.Collection
});