Search code examples
javascriptjquerybackbone.js

Assigning ' this' context in Backbone js view


I am new to Backbone js, but enjoying the framework. I am doing a project where there are some list items and in those list items there is a div which will have the html template with some attributes of a model. My Html is:

<ul class="product-grid">
<li class="product-lists thumbnail-lists">
<div class="inline-block product-item-img-container">
<div class="product-featured-image">
    <a href="" data-dtsTooltip data-title="eCommerce Theme" data-price="260"><img src="assets/img/products/pt-1.png" ></a>
<div class="product-caption">
<a href="http://google.com">View</a>
</div>
</div>

<div class="product-featured-title">
<h1 class="entry-title">Go Fast-Transport &amp; Logistics PSD Template</h1>
</div>
</div> <!-- product-item-img-container -->
<div class="inline-block product-description-container">
    <p>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam.
    </p>
</div>
<div class="inline-block product-price-container text-center">
    <h3 class="product_price">Rs.25000 </h3>
    </div>
    <div class="big-thumbnail-container" style="display:block; width:100%; height:100px; background:#666666;"></div>
</li>

<li class="product-lists thumbnail-lists">
<div class="inline-block product-item-img-container">
    <div class="product-featured-image">
    <a href="" data-dtsTooltip data-title="eCommerce Theme" data-price="260"><img src="assets/img/products/pt-1.png" ></a>
    <div class="product-caption">
    <a href="http://google.com">View</a>
    </div>
</div>

    <div class="product-featured-title">
    <h1 class="entry-title">Go Fast-Transport &amp; Logistics PSD Template</h1>
    </div>
    </div> <!-- product-item-img-container -->
<div class="inline-block product-description-container">
    <p>
                Sed ut
    </p>
    </div>
<div class="inline-block product-price-container text-center">
    <h3 class="product_price">Rs.25000 </h3>
</div>
<div class="big-thumbnail-container" style="display:block; width:100%; height:100px; background:#666666;"></div>
</li>

</ul>

I want to append .product-description content inside the .big-thumbnail-container for each .thumbnail-lists lists

I have coded in js file:

var FeaturedThumbnailModel = Backbone.Model.extend({

    defaults:{
        thumbImg_attr              : 'data-dtsTooltip',
        data_product_url_container :'.product-caption',
        data_title                 :'.product-featured-title',
        data_preview               :'previewUrl',
        data_description_container : '.product-description-container',
        data_price                 : '.product-price-container'

    },

    initialize: function(){
        this.tooltipFunction();

    },


    tooltipFunction: function(){

        var thumbnailIdentifier           = $('[' + this.get( 'thumbImg_attr') +']'),
            parentThumbIdentifier         = thumbnailIdentifier.closest('.thumbnail-lists'),
            product_url_cont              = $(this.get('data_product_url_container')),
            product_title                 = $(this.get('data_title')),
            product_Description_container = $(this.get('data_description_container')),
            product_price_container       = $(this.get('data_price'));

var Featured_Img        = parentThumbIdentifier.find( thumbnailIdentifier ).children('img').attr('src'),
            Product_url         = parentThumbIdentifier.find( product_url_cont ).children('a').attr('href'),
            Product_Title       = parentThumbIdentifier.find( product_title ).children('.entry-title').text(),
            Product_Description = parentThumbIdentifier.find( product_Description_container ).children('p').text(),
            Product_Price       = parentThumbIdentifier.find( product_price_container ).children('.product_price').text();

        this.set({
               data_img          : Featured_Img,
               data_product_link : Product_url,
               data_title        : Product_Title,
               data_description  : Product_Description,
               data_price        : Product_Price
        });
console.log(this);

    return this;
    }

});

var FeaturedThumbnailView = Backbone.View.extend({

    //model :  new FeaturedThumbnailModel(),
    el:".big-thumbnail-container",
    template :_.template("<strong><%= data_description %></strong>"),
    initialize: function(){
        this.model = new FeaturedThumbnailModel();
        this.render();
},

    render: function(){
     var eles = $(this.$el);
       var temp = this.template(this.model.attributes);
       _.each(eles, function(element){
        $(element).append( temp );

       });

       //console.log(this.model.get('data_description'))

    return this;
    }
});

$(document).ready(function(){
var thumbFunc = new FeaturedThumbnailModel({

    });
var thumbView = new FeaturedThumbnailView({
    el: '.big-thumbnail-container'

});
})

The html is appending, but what is happening, that since there are two list items in the HTML and the .big-thumbnail-containerare in the both lists, the content is same content is appending in both lists as a result data_description are repeating, instead of data_description in each respective .big-thumbnail-container. I am sure the 'this' context I am unable to assign.

The demo link: http://damiracle.com/practise/theme/html/collection.php

Can somebody help me? Thanks in advance

Thanks @TJ for your help. I have changed the code. Am I right in my route? Your comment will be highly appreciated

var FeaturedThumbnailModel = Backbone.Model.extend({
 defaults:{
    thumb_lists : '.thumbnail-lists',
    descriptionClass :'.product-description-container',

 }



});

var FeaturedThumbnailView = Backbone.View.extend({
    initialize: function(){
        this.model = new FeaturedThumbnailModel();

    },

    events : {
        'click' :'onDescription'
    },


    onDescription: function(e){
        e.preventDefault();
        var Element = this.$el;

        var templT = $(this.model.get('descriptionClass'));
        console.log(Element);

        var html = Element.parent().find(templT).html();
            console.log(html)

            var descriptionTemplate = _.template(html);

            alert(html);

        return this;

    }


});

var FeaturedThumList = Backbone.View.extend({

    render:function( thumbnailContainer ){

        var targets = $('.thumbnail-lists > .big-thumbnail-container');
  _.each( targets, function( thumbnailContainer ){
    new FeaturedThumbnailView({ el: thumbnailContainer});


  }, this);

    }

});

$(document).ready(function(){
var featuredThumblist = new FeaturedThumList();
 featuredThumblist.render('.thumbnail-lists');
});

Solution

  • el option is supposed to be/match a specific element.

    You need to iterate over .big-thumbnail-containers and create new instance of FeaturedThumbnailView with specific el, something like:

    $('.thumbnail-lists .big-thumbnail-container').each(function(thumbnailContainer){
         // You need to save reference to view instance for future clean up
         new FeaturedThumbnailView({el: thumbnailContainer});
    });
    

    Also, model is for storing data, not for storing things like jQuery selectors or methods like tooltipFunction, they should be part of view. And you shouldn't be doing things like $(this.$el).