Note that there are some explanatory texts on larger screens.

plurals
  1. POBackbone.Marionette Scope issue when triggering the same event multiple times with different arguments
    text
    copied!<h1>The situation</h1> <p>I'm trying to render an overview of a nested data structure with models and collections. In particular, i'm loading a <code>SubjectsCollection</code>, where each subject has a few attributes, one of which is supposed to be a nested <code>LessonsCollection</code>.</p> <p>My Controller loads the <code>SubjectsCollection</code>. Once the <code>SubjectsCollection</code> is loaded, the controller then renders a <code>SubjectListView</code> (a <code>Marionette.CollectionView</code>) with the <code>SubjectsCollection</code> and shown in a <code>Marionette.Region</code>.</p> <p>Each <code>SubjectModel</code> within the <code>SubjectListView</code> gets rendered as a <code>SubjectLayout</code> (a <code>Marionette.Layout</code>).</p> <p>Once the <code>SubjectListView</code> is shown in the <code>Marionette.Region</code>, a function cycles through the <code>SubjectLayout</code>'s and triggers an event (<code>package-definition:subject:layout:ready</code>) on <code>App.vent</code> (a <code>Marionette.EventAggregator</code>) for each <code>SubjectLayout</code>, passing the <code>SubjectLayout</code> as an argument for any Callbacks to receive.</p> <h1>The desired effect</h1> <p>A method called <code>openLessons</code> reacts to the <code>package-definition:subject:layout:ready</code> event and loads a <code>LessonsCollection</code>. This should happen multiple times (Once for each <code>SubjectLayout</code> that was rendered).</p> <p>Each <code>LessonsCollection</code> should render a <code>LessonsListView</code> and the <code>LessonsListView</code> should be shown in a region in the <code>SubjectLayout</code> of the <code>SubjectsCollection</code> to which they belong.</p> <p>The <code>SubjectLayout</code> instance is supposed to be passed as an argument to the <code>openLessons</code> method, so each <code>LessonsListView</code> can be shown in the assigned region of it's corresponding <code>SubjectLayout</code>.</p> <h1>The Code</h1> <p>Here's the code I've got so far:</p> <pre><code>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); } }); </code></pre> <h1>The problem</h1> <p>Despite the the fact that <code>package-definition:subject:layout:ready</code> gets triggered multiple times, and multiple <code>LessonsCollection</code>'s get loaded. Only the last <code>SubjectLayout</code> receives its <code>LessonsListView</code>.</p> <p>Also, each <code>SubjectsCollection</code>'s 'lessons' attribute contains the very last <code>LessonsCollection</code> that got loaded.</p> <p>So obviously there's a scoping problem here.</p> <h1>The questions</h1> <p>The questions are:</p> <ol> <li>Why do all <code>SubjectsCollection</code> get their 'lessons' attribute overwritten with the last <code>LessonsCollection</code>?</li> <li>Why does only the last <code>SubjectLayout</code> instance receive a <code>LessonsListView</code>?</li> <li>How do I resolve the problem?</li> </ol>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload