A View normally expects an object with these attributes before it can render:
{ el: '#someelement', model: someModel }
A View also allows us to bind the model's events to functions in the view:
initialize: function() { this.model.bind('change', this.renderFromModel, this); }, render: function() { $(this.el).html(this.template(this.model.toJSON())); return this; }, renderFromModel: function() { var t = _.template($('#some-template').html()); $('item-' + this.cid).html(t(this.toJSON())); return this; },
The problem is that the first time we instantiate a View for rendering, it is expecting an object with a Model in it; and the second time we render the view when it is called from within the Model, it is not. Because of this, I end up creating two render() functions.
Is there a better way of achieving single item render that can also respond to model.change() events?
i think you need to ensure your render method is always bound the view by calling underscore.js' bindAll method.
SomeView = Backbone.View.extend({ initialize: function(){ _.bindAll(this, "render"); this.model.bind('change', this.render); }, render: function(){ $(this.el).html(this.template(this.model.toJSON())); return this; } });
A better solution is to use the listenTo function:
SomeView = Backbone.View.extend({ initialize: function(){ this.listenTo(this.model, 'change', this.render); }, render: function(){ this.$el.html(this.template(this.model.toJSON())); return this; } });
This way the view object is aware of the bindings it made, and all of them can be removed with the stopListening function and doesn't need to call bind or bindAll explicitly. Last but not least the code is cleaner in my opinion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With