1
votes

I have a series of comments on a page, which can be edited. My idea was to render the comments by Rails and preload a json with all those comments in a Backbone Collection.

Then I would poll every x seconds, to see if there are changes. Normally I render the collection by looping over all the models, and create a view for each item. When a model gets updated, so will the view (comment im this case).

But my question is this, how do you bind a view to the model, when the view is already in the DOM. Especially since the view had a dynamic id. There is no point in rendering the view, since it's already there. When you render a view, backbone binds it through somekind of cid.

The only solution I can think of, is by setting an id in the dom object on pageload. iow

<div id="comment-<%= content.id %>"></div>

. And then in the initialize of the view, reset the id

class Comment extends Backbone.View
    initialize: ->
       @id = "comment-" + @model.get('id')

But I'm not sure if thats the way to go. Would events still be binded?

1

1 Answers

2
votes

Special for you :)

var CommentsView = Backbone.View.extend({
  tagName : 'ul',
  comments : {},
  initialize : function () {
    this.listenTo(this.collection, 'add', this.addComment);
    this.listenTo(this.collection, 'remove', this.removeComment);
    this.listenTo(this.collection, 'change', this.updateComment);
  },
  addComment : function (model) {
    this.comments[model.id] = new CommentView({model:model});
    this.$el.append(this.comments[model.id].render().$el);
  },
  removeComment : function (model) {
    this.comments[model.id].remove();
    this.comments[model.id] = null;
  },
  updateComment : function (model) {
    this.comments[model.id] = new CommentView({model:model});
    this.$('[data-id="' + model.id + '"]').before(this.comments[model.id].render().$el).remove();
  }
});

var CommentView = Backbone.View.extend({
  tagName : 'li',
  template : _.template('<div data-id="<%= id %>"><%= name %>: <%- message %></div>'),
  render : function () {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
  }
});

// comments
var initialComments = [{id:1, name:'user1', message:'great!'}, {id:2, name:'user2', message:':)'}];
var actualComments = [{id:1, name:'user1', message:'great! [edited]'}];

var comments = new Backbone.Collection();
var commentsView = new CommentsView({collection:comments});

// show comments
commentsView.render().$el.appendTo('body');

// simulate fetch
comments.add(initialComments);

// simulate update
_.delay(function() {
  comments.update(actualComments);
},
2000);

jsfiddle