Question

It is pretty basic thing but I still can't find the answer. I need to set View's el: to div which is in underscore.js template.

<script id="product" type="text/template">
    <div class="productInfo"></div>
    <div class="prices"></div>
    <div class="photos"></div>
</script>

The first view renders the product template. I need to render other Views to divs in this template. I don't know how to set el:, because el: '.prices' just don't work with divs in template.

This Views structure is similar to How to handle initializing and rendering subviews in Backbone.js?. But I use template instead of rendering to existing divs.

Was it helpful?

Solution 2

Render the parent view, then assign the '.prices' as the el of the child:

var ParentView = Backbone.View.extend({
    render : function() {
        var html='<h1>Parent View</h1><div class="productInfo"></div><div class="prices"></div><div class="photos"></div>';
        this.$el.html(html);

        var prices = new PricesView({
            el : this.$('.prices')
        });
        prices.render();
    }
});

var PricesView = Backbone.View.extend({
    render : function() {
        var html='<h2>Prices View</h1>';
        this.$el.html(html);
    }
});

// Create a parent view instance and render it
var parent = new ParentView({
    el : $('.parent')
});

parent.render();

Working example on jsfiddle: http://jsfiddle.net/JpeJs/

OTHER TIPS

So the problem is using a CSS selector string for this.el won't find anything if the matching <div> is not attached to the page's DOM. In the case of you <script> tag template, the contents of the <script> tag are not attached DOM nodes, there are just a single text node.

One option given your HTML would be to just forget about the <script> tag and put your empty <div> tags straight into the HTML. They are empty and thus should be harmless and invisible until you actual render some content within them. If you do that, el: '.productInfo:first' should work fine.

Other than that, you'll need to put logic into your parent view along these lines:

  • Render the template into a detached DOM node
  • Search that detached DOM node for subview divs
  • Map the subview div to the corresponding backbone view subclass
  • instantiate and render the subview, then use something like this.$el.find('.productInfo').replaceWith(productInfoView.el) to put the rendered HTML into the parent view at the right location

My general comment is that views should render to detached DOM nodes and leave it to other components such as the router or layout managers to decide where in the real DOM they get attached. I think this makes the views more reusable and testable.

from version 0.9.9, backbone alaws you to define the el property of a view as a function :

When declaring a View, options, el and tagName may now be defined as functions, if you want their values to be determined at runtime.

Assuming that the subviews are created after the main view, this might help you if your subviews are aware of their parent :

 SubView = Backbone.View.extend({
     el : function(){
         return this.parent.$('.prices');
     }
 });

 var subViewInstance = new SubView({parent : theParentView});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top