0

I am building a backbone application at the moment, and I have run into a bit of a problem when building a view, the view is built by loop over a collection and outputting HTML. Now the I can output the HTML fine, and see it in my browser, however it always seems to overwrite the previous data, so for example, I am looping over my collection and spitting out the name from the model I should get a list that looks like this,

  • File Number 1
  • File Number 2
  • File Number 3

however the output I am getting is,

  • File Number 3
  • File Number 3
  • File Number 3

So basically on each loop it overwrites itself. How can I stop this happening, I assume it a specifity problem when I am rendering the template?

Below is my view code,

app.FileListItem = Backbone.View.extend({

tagName: 'li',
className: 'image-thumb',

template: _.template($('#tpl-files-image-panel').html()),

events: {

},

initialize: function() {

},

render: function() {

    this.model.set({"timeago" : $.timeago(this.model.get('last_modified'))});
    //console.log(this.model);
    this.$el.html(this.template(this.model.toJSON()));

    return this;

},

});

and it gets called like this,

item.get('files').each(function(file){
    var itemFileListItem = new app.FileListItem({
        model: file
     });

     that.$el.find('.tab-content.files:first').find('.image-grid').append(itemFileListItem.render().el);
 });

item.get('files') looks like this, enter image description here

and that.$el is article.item of which there are multiple on the page created by another loop.

Can anyone suggest a solution to stop the data getting overwritten on each loop?

Udders
  • 6,914
  • 24
  • 102
  • 194
  • 5
    Hi Udders, have you considered creating a JSFiddle with a minimal example of what's wring with your app? There are [backbone.js fiddles](http://jsfiddle.net/icoxfog417/pfxP5/) out there, yours should be too! I'm not that familiar with backbone, but having a fiddle to play with, it will be worth a try! – Pavel May 26 '14 at 16:34
  • The code looks fine to me. Since you are using `append` method, should not overwrite any content. The issue might be with `item` collection content. Are you copying the models to `item`? If so can you share that code. – Manish Mulimani May 27 '14 at 01:54
  • Can you share the template (`#tpl-files-image-panel`) content? – Rida BENHAMMANE May 28 '14 at 00:08
  • Does the `//console.log(this.model);` prints differents models? – Rida BENHAMMANE May 28 '14 at 01:49
  • Can you show what `$('#tpl-files-image-panel').html()` looks like? That seems like the likeliest place the problem could be. – otus May 28 '14 at 10:36
  • You have a situation similar to one described in http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example . There are also some details on how to fix it and what is the cause of it. – Kiril May 30 '14 at 09:32
  • Why don't you just console.log() all possible combinations to see if you get the correct jQuery object to append to? Of course something most be wrong there. Where's the var that = this? Btw, you can also use _.bind(function(){},this) for that. – html_programmer Jun 02 '14 at 13:36

1 Answers1

2

I think what's happening may have something to do with the file reference being overwritten in each iteration of .each()

I've run into this problem several times and a very simple solution is to pass the reference to an outside function to construct the independent views. With more of your code to look at I'm sure I could investigate more thoroughly. Please give this a try:

item.get('files').each(function(file){
    that.$el.find('.tab-content.files:first').find('.image-grid').append(returnItem(file).render().el);
});

function returnItem(file) {
    var itemFileListItem = new app.FileListItem({
        model: file
    });
    return itemFileListItem;
}
aecend
  • 2,432
  • 14
  • 16