I'm trying to render an overview of a nested data structure with models and collections.
In particular, i'm loading a SubjectsCollection
, where each subject has a few attributes, one of which is supposed to be a nested LessonsCollection
.
My Controller loads the SubjectsCollection
.
Once the SubjectsCollection
is loaded, the controller then renders a SubjectListView
(a Marionette.CollectionView
) with the SubjectsCollection
and shown in a Marionette.Region
.
Each SubjectModel
within the SubjectListView
gets rendered as a SubjectLayout
(a Marionette.Layout
).
Once the SubjectListView
is shown in the Marionette.Region
, a function cycles through the SubjectLayout
's and triggers an event (package-definition:subject:layout:ready
) on App.vent
(a Marionette.EventAggregator
) for each SubjectLayout
, passing the SubjectLayout
as an argument for any Callbacks to receive.
A method called openLessons
reacts to the package-definition:subject:layout:ready
event and loads a LessonsCollection
. This should happen multiple times (Once for each SubjectLayout
that was rendered).
Each LessonsCollection
should render a LessonsListView
and the LessonsListView
should be shown in a region in the SubjectLayout
of the SubjectsCollection
to which they belong.
The SubjectLayout
instance is supposed to be passed as an argument to the openLessons
method, so each LessonsListView
can be shown in the assigned region of it's corresponding SubjectLayout
.
Here's the code I've got so far:
var PackageDefinition_Overview_Controller = Controller.extend({
...
Data: {
packageDefinition: {
// attributes: {
// foo: 'bar',
// subjects: [{
// attributes: {
// baz: 'quux',
// lessons: []
// }
// }]
// }
}
},
// Initialization
//---------------
initialize: function() {
...
this.bindTo(App.vent, "package-definition:subject:layout:ready", this.openLessons);
},
...
openSubjects: function(packageDefinitionOverviewLayout) {
var that = this,
packageDefinition = packageDefinitionOverviewLayout.model;
packageDefinition_id = packageDefinition.get('id'),
subjects = packageDefinition.get('subjects') || new SubjectsCollection(),
subjectsRegion = packageDefinitionOverviewLayout.subjects;
...
subjects.load(packageDefinition_id);
...
subjects.isLoaded.done(function() {
packageDefinition.set({
subjects: subjects
});
that.showSubjectListView(subjectsRegion, subjects);
});
...
},
openLessons: function(subjectLayout) {
var that = this,
subject = subjectLayout.model;
subject_id = subject.get('id'),
lessons = subject.get('lessons') || new LessonsCollection(),
lessonsRegion = subjectLayout.lessons;
...
lessons.load(subject_id);
...
lessons.isLoaded.done(function() {
console.log('Data', that.Data);
subject.set({
lessons: lessons
});
that.showLessonsListView(lessonsRegion, lessons);
});
...
},
...
showSubjectListView: function(region, subjects) {
var subjectsListView = new SubjectsListView(subjects);
region.show(subjectsListView);
// Time to load the Lessons
subjectsLayouts = subjectsListView.children;
_.each(subjectsLayouts, function(subjectLayout) {
App.vent.trigger("package-definition:subject:layout:ready", subjectLayout);
}, this);
},
showLessonsListView: function(region, lessons) {
var lessonsListView = new LessonsListView(lessons);
region.show(lessonsListView);
}
});
Despite the the fact that package-definition:subject:layout:ready
gets triggered multiple times, and multiple LessonsCollection
's get loaded. Only the last SubjectLayout
receives its LessonsListView
.
Also, each SubjectsCollection
's 'lessons' attribute contains the very last LessonsCollection
that got loaded.
So obviously there's a scoping problem here.
The questions are:
SubjectsCollection
get their 'lessons' attribute overwritten with the last LessonsCollection
?SubjectLayout
instance receive a LessonsListView
?Well, that's a bit embarassing.. Turns out the problem all along was I accidentally defined some vars in the global scope, such as here:
var that = this,
subject = subjectLayout.model; // <-- should've been a comma... *headdesk*
subject_id = subject.get('id'),
lessons = subject.get('lessons') || new LessonsCollection(),
lessonsRegion = subjectLayout.lessons;