0

I'm a beginner in Backbone trying to get a sample page up and running with multiple instances of a Carousel. Here's how my HTML looks like

<div class="en-carousel" id="one" data-href="/js/models/json/carousel.json" data-content-id=""></div>
<div class="en-carousel" id="two" data-href="/js/models/json/carousel2.json" data-content-id=""></div>
<div class="en-carousel" id="three" data-href="/js/models/json/carousel3.json" data-content-id=""></div>

The data is fetched using the Model and the render method of view iterates over the 'el' object of my View object. The model fetch is associated with a success handler which initiates the carousel. The controller code looks like

define([
  'jquery',
  'backbone',
  'handlebars',
  'text!view/carousel.html',
  'plugin/jquery.bxslider.min',
  'TPL'
], function($, Backbone, Handlebars, carouselTemplate, $bx, TPL){

  var CarouselModel = Backbone.Model.extend({
    setURL: function(url){
      this.url = url;
    }
  });

  var CarouselView = Backbone.View.extend({
    el: '.en-carousel',
    model: new CarouselModel(),
    initialize: function () {

    },
    render: function () {
      var that = this;
      this.$el.each(function(){

        //that.model.url = $(this).data('href');
        that.model.setURL($(this).data('href'))

        that.listenTo(that.model,'change', that.onSuccess);
        that.model.fetch();

      });


    },

    onSuccess: function(response, status, xhr){

      var tpl = window["ENX"]["templates/handlebars/carousel.html"](this.model.get('response'));
      $(this.el).append(tpl);
      $(this.el).find('ul.carousel').bxSlider();

    },

    ajaxFail: function(){
      alert(2)
    }
  });
  return CarouselView;
});

I'm using Handlebars for templating. The problem here is the listenTo event is fired n*n times for n instances. So for 3 carousel I'm getting 9 carousels in total and all of them are being appended to div#one

Ankur
  • 791
  • 4
  • 15
  • A carousel has multiple items right? Sounds like each item should be a model, each carousel a collection - so you are dealing with 3 collections here with many models (carousel items) inside. I extended View to have a special CollectionView for instances like this, designed to render out models efficiently and using a ItemView for each one. – Dominic Jul 31 '14 at 08:52
  • There are almost no chance that my carousel slides will change post load. So the model that way if pointing to Carousel itself will barely change. Hence instead of having my Carousel as a Collection, I took it up as a model. It'll have some static image paths, or video ids that will be processed on render. The part where I'm stuck is on how to use only one controller and iterate over all the instances of carousel and populating the slides appropriately. What I was looking for was to looping over the carousel container nodes inside my view. – Ankur Jul 31 '14 at 09:59
  • Per the answer below this looping should run outside the view and the view should be invoked thrice. – Ankur Jul 31 '14 at 10:00

1 Answers1

0

The solution is simple: replace the entire content of el when the model changes.

initialize: function () {
    this.model.fetch().done(function () {
        this.render();
        this.listenTo(this.model,'change', this.render.bind(this));
    }.bind(this));
},

render: function () {
    var tpl = window["ENX"]["templates/handlebars/carousel.html"](this.model.get('response'));
    this.$el.html(tpl);
    this.$el.find('ul.carousel').bxSlider();
}

There is also no need to iterate over el because it is just a single element.

jgillich
  • 71,459
  • 6
  • 57
  • 85
  • I have multiple carousels here. The 'el' is pointing to a class name 'en-carousel', and all of them is being fed data through a different end-point. So how do I populate all three of them with different data using the same view. – Ankur Jul 31 '14 at 07:19
  • 2
    @Ankur Then you are using `el` wrong. It is meant to be a single element; if you have multiple elements, create multiple views and pass a different model instance to each. – jgillich Jul 31 '14 at 07:24
  • So that means the loop should run outside the view and the view should be invoked thrice. – Ankur Jul 31 '14 at 10:00
  • Thanks for the suggestion, was not able to solve it through this approach though. – Ankur Aug 01 '14 at 08:42