开发者

Using backbone events on views not yet added to the DOM - rendering issue

开发者 https://www.devze.com 2023-04-01 10:56 出处:网络
Short story... I have nested views but only the top level view can work with events because I am only passing in the \'el\' property to the top level view.

Short story... I have nested views but only the top level view can work with events because I am only passing in the 'el' property to the top level view.

Long story...

I am creating a timeline project using backbone as JS/GUI client side app. My template for rendering the horizontal timeline is like this:

<script type="text/template"开发者_Python百科; id="yearGroups">
<![CDATA[
   <% _.each(columns, function(item,i) { %>
      <div class="yearGroup">
         <h2><%= item.yearLabel %></h2>
         <div class="years">
            <% _.each(item.years, function(year, b) { %>

               <div class="year">

                  <% _.each(year.searchGroups, function(sg, sg_index) { %>               
                     <%= jQuery(sg.viewEl).html() %>
                  <% }); %>

               </div>
            <% }); %>
         </div>
      </div>
   <% }); %>
]]>
</script>

There can be multiple searches and therefore multiple searchGroups per year. Each searchGroup contains eventBlocks as a wrapper for each search result.

Below is a code snippet from the loop which creates the SearchGroupViews (which creates the eventBlocks not shown here).

var events = eventCollection.getEventsInYear(year);
if(events.length > 0) {
   var sgv = new SearchGroupView({results: events, searchID: 'search1'});
   this.searchGroups.push(sgv);
   renderedResults.push({viewEl:sgv.render().el});
}

renderedResults is then eventually passed through to the template like this:

$(this.el).html(this.template({columns:col}));

... and rendered under each .year using:

jQuery(sg.viewEl).html().

All of this means that my nested views don't receive any events because they don't have a container div passed in using the 'el' attribute. They don't have a container because that's rendered after all the views are built (see first code block).

My current solution is to use a global eventManager that can be used as an event handler to notify views when the top level view calls an eventManger.trigger(..). This is not ideal.

There must be a solution that allows my nested views to pick up on the events after they have been rendered? Or do I need to pre-render the top level view template and specify el attributes like {el: '.year.yearID-1984'} and {el: '.searchGroup.groupID-6'}?

Ideally I could render sg.viewEl and not simply the html output from that object and the view would then be self aware of where it is. ... but I know that's not possible :(

Hope this is clear.


I implemented an ok solution close to what was described in my question...

//global event notifier system
window.vent = _.extend({}, Backbone.Events);
window.app = new TimelineRouter();

After rendering the top level view, I then call:

window.vent.trigger('ev:redelegate', {});

This event is then captured in each view init function....

this.model.view = this;
var _this = this;

window.vent.bind('ev:redelegate', function(event) {
   var nid = _this.model.get('nid');
   _this.el = $('.nid-'+nid);

   _this.delegateEvents();
});

...so that the view can update the el property. This all relies on a unique class name being used to find the el (eg, class="nid-1234").

I'm guessing this would then be the same as setting the view el property on init given that I know the id it's based on. This assumes that backbone uses .live(..) for finding the el: ".nid-1234" DOM obj.

0

精彩评论

暂无评论...
验证码 换一张
取 消