View depends on another view being rendered

64 views
Skip to first unread message

ChrisM

unread,
Jan 12, 2017, 12:41:27 PM1/12/17
to backbonejs
I my Backbone app I have two interdependent subviews within the main App view: one which displays a music score rendered using Vexflow (Javascript music notation package), and another below which displays an analysis of the score, also using Vexflow but with some extra objects (text, lines, clickable elements, etc).

I have a problem, however, in that a lot of the data I need for the analysis view doesn't come into existence until the score view has been rendered (this is due to the way Vexflow renders things). For example, the x coordinate of a musical note is only available after the note has been drawn (the same isn't true of the y coordinate). Below is a schematic my app view set up:

    var AppView = Backbone.View.extend({
   
     
//...
   
      initialize
: function() {
       
this.scoreView = new ScoreView();
       
this.analysisView = new AnalysisView({
          data
: this.getAnalysisData()
       
});
     
},
   
      render
: function() {
       
this.scoreView.render();
       
this.analysisView.render();
       
return this;
     
},
   
      getAnalysisData
: function() {
       
// Performs anaysis of this.scoreView,
       
// and returns result.
     
}
   
   
});



My work around is to move the analysis view setup into the render method, after the score view has been rendered. I dislike doing this, as the getAnalysisData method can be quite expensive, and I believe the render method should be reserved simply for rendering things, not processing.

So I'm wondering if - since there doesn't seem to be a Vexflow solution - there is a Backbone pattern that might fix this. I am familiar with the 'pub/sub' event aggregator pattern for decoupling views, as in:

   
 this.vent = _.extend({}, Backbone.Events);


So on this pattern the analysis view render method subscribes to an event fired after the score view is rendered. I'm not sure how this would alter my code, however. Or perhaps use listenTo, like this:
   
    // Score subview.
   
var ScoreView = Backbone.View.extend({
   
      initialize
: function() {
       
this.data = "Some data";
     
},

      render
: function() {
        alert
('score');
       
this.trigger('render');
     
}
   
   
});
   
   
// Analysis subview.
   
var AnalysisView = Backbone.View.extend({
   
      initialize
: function(options) {
       
this.data = options.data;
     
},
   
      render
: function() {
        alert
(this.data);
       
return this;
     
}
   
   
});
   
   
// Main view.
   
var AppView = Backbone.View.extend({
   
      el
: "#some-div",
   
      initialize
: function() {
       
this.scoreView = new ScoreView();
       
var view = this;
       
this.listenTo(this.scoreView, 'render', this.doAnalysis); // <- listen to 'render' event.
     
},
   
      render
: function() {
       
this.scoreView.render();
       
return this;
     
},
   
      doAnalysis
: function() {
       
this.analysisView = new AnalysisView({
          data
: this.getAnalysisData()
       
});
       
this.analysisView.render();
     
},
   
      getAnalysisData
: function() {
       
return this.scoreView.data;
     
}
   
   
});


Of course, the analysis step is still effectively being done during the render process, but this seems a better pattern. It seems more like the Backbone way of doing things. Am I right? Or am I missing something?

I don't necessarily have to create the analysis view in the doAnalysis, I could still do that in the main view initialize (at the moment I'm not). But doAnalysis has to run after the score view has rendered, otherwise it cannot access the relevant score geometry information.

Uzi Kilon

unread,
Jan 12, 2017, 12:59:31 PM1/12/17
to backb...@googlegroups.com
IMHO, a better way is for views to communicate through events on a shared model they both have access to.
This way we keep things loosely coupled and make it easier to tweak/change later.

In the MV* paradigm data/state goes in models, presentation goes in view.

My 2c
/Uzi

--
The Unofficial Backbone.js Group
 
Job Board: https://groups.google.com/forum/#!topic/backbonejs/wHRdZczyOEc
---
You received this message because you are subscribed to the Google Groups "backbonejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to backbonejs+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jason Crawford

unread,
Jan 12, 2017, 2:07:16 PM1/12/17
to backb...@googlegroups.com
I agree, if there are calculations that result in data that a view needs, those calculations should be done in a model and the data should be accessible from that model. If a view is doing those calculations, push the data and logic into the model layer. Then each view can just listen to the models it needs.

To unsubscribe from this group and stop receiving emails from it, send an email to backbonejs+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
The Unofficial Backbone.js Group
 
Job Board: https://groups.google.com/forum/#!topic/backbonejs/wHRdZczyOEc
---
You received this message because you are subscribed to the Google Groups "backbonejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to backbonejs+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Fieldbook: Create a database, as easily as a spreadsheet

ChrisM

unread,
Jan 12, 2017, 2:43:03 PM1/12/17
to backbonejs
Thank you for your helpful replies, Uzi and Jason. Just to clarify, my two subviews do have their own models - the AnalysisView model is updated by doAnalysis.

My models contain raw note (pitch, duration) data, and that's it. So much of what I'm doing depends on complex cross-cutting relationships between objects sitting at different layers of the hierarchy of the musical score. For example, I might have a line drawn between a note in one stave to a note in another, and other complex interrelationships. These are hard to express in terms of a model, and in any case setting up these relationships depends on certain things (x coordinates, for example) which only come into existence after the score has been rendered.

So my model for the ScoreView is used to create a Vexflow 'score', which knows how to render itself, and it's from processing this that the data for the AnalysisView model is arrived at.
To unsubscribe from this group and stop receiving emails from it, send an email to backbonejs+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
The Unofficial Backbone.js Group
 
Job Board: https://groups.google.com/forum/#!topic/backbonejs/wHRdZczyOEc
---
You received this message because you are subscribed to the Google Groups "backbonejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to backbonejs+...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages