I am relatively new to Backbone and I am running into this problem.
I am using Backbone with DustJS
My template looks something like this - index.dust
<div id="parentView">
<div class="section">
{>"app/inc/responseMessage" /}
<div class="userDetails">
{! A button to get user details !}
</div>
</div>
</div>
This is my partial below - responseMessage.dust
<div id="responseMessage">
{@eq key="{data.success}" value="true"}
<div class="alert alert-success success" role="alert">success</div>
{/eq}
</div>
My JS looks like this
initialize: function() {
this.responseMessageView = this.responseMessageView ||
new ResponseMessageView({
model: new Backbone.Model()
}); // View is for the partial
this.model = this.model || new Backbone.Model(); //View for the whole page
},
Below function is called when an event occurs and it does a POST and returns successfully.
primaryViewEventTrigger: function(event){
//Button click on `index.dust` triggers this event and does a POST event to the backend
this.listenToOnce(this.model, 'sync', this.primaryViewSuccess);//this will render the whole view.
this.listenToOnce(this.model, 'error', this.primaryViewError);
this.model.save({data: {x:'123'}});
}
responseViewEventTrigger: function(event){
//Button click on `responseMessage.dust` triggers this event and does a POST event to the backend
this.listenToOnce(this.responseMessageView.model, 'sync', this.responseViewSuccess);//it should only render the partial view - responseMessage.dust
this.listenToOnce(this.responseMessageView.model, 'error', this.primaryViewError);
this.responseMessageView.model.save({data: {x:'123'}});
}
primaryViewSuccess: function(model,response){
this.model.set('data', response.data);
this.render();
}
responseViewSuccess: function(model,response){
this.responseMessageView.model.set('data', response.data);
console.log(this.responseMessageView.model);
this.responseMessageView.render(); // Does not work in some cases
}
My implementations of the callback function
exports.sendEmail = function sendEmail(req, res){
req.model.data.success = true;
responseRender.handleResponse(null, req, res);
};
this.model
belongs to the model of the whole page. Whereas this.responseMessageView.model
is the model for the partial.
Question: This works perfectly fine in most of the cases. There is one case where it does not render the partial with the latest model values. When I click on the button on index.dust
and primaryViewSuccess
is executed. After which I click on another button and trigger responseViewEventTrigger
. It does the POST successfully and it comes to responseViewSuccess
and stores it in the model too. But it does not show it on the frontend. data.success
is still not true whereas console.log(this.responseMessageView.model)
show that attributes->data->success = true
But the same behavior when I refresh the page it all works perfect. Its just that when primaryViewSuccess
is called and then responseViewSuccess
its not taking the latest model changes. In other words model is being updated but the DOM remains the same.
What am I missing here? Thanks for your time!
You're hitting the classic Backbone render-with-subviews gotcha: When you render the index view, you are replacing all of the DOM nodes. That includes the DOM node that your responseMessageView
instance is tied to. If you inspect the responseMessageView.el
you'll actually see that it has been updated with the new model data, however the element isn't attached to the index's DOM tree anymore.
var Parent = Backbone.View.extend({
template: _.template(''),
render: function() {
this.$el.html(this.template());
},
initialize: function() {
this.render();
this.child = new Child();
this.$el.append(child.el);
}
});
Here when you manually call render, child.el
will no longer be in the
parent.el
(you can check using the inspector).
The simplest fix here is to call child.setElement
after the parent renders with the newly rendered div#responseMessage
element. The better fix is to detach the responseMessageView
's element beforehand, and reattach after:
var Parent = Backbone.View.extend({
render: function() {
this.responseMessageView.$el.detach();
this.$el.html(this.template(this.model.toJSON()));
this.$el.find('#responseMessage').replaceWith(this.responseMessageView.el);
}
});
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