I work on a large enterprise application with BackboneJS. One page in the application is constructed using multiple sub-system calls via REsT. How do I make sure that, all the services required to load the page has been called and the templates are binding is completed?
For example, I have a MasterView
, that takes care of the collection.fetch()
of each child views, like this.
myApp.views.MasterView = Backbone.View.extend({
initialize: function(params) {
var self = this;
this.collection.fetch({
success: function(resp) {
self.collection.bind("reset", self.render(), self);
},
error: function(xhr, xhrStatus) {
// push error message, in case of fetch fails.
}
});
},
render: function() {
var self = this;
this.collection.each(function(model) {
if (model.get('authorize') && model.get('status') === "success" && model.get('data').length > 0) {
self.bindTemplate(model.get('data')[0]);
}
});
}
});
I have a view set for the page, that takes care of rendering two other views CustomerInfo and CustomerAccounts. The view goes like this.
myApp.views.CustomerView = Backbone.View.extend({
initialize: function() {
var customerInfo = new myApp.collection.CustomerInfo();
new myApp.views.CustomerInfo({el: $("#infoContainer"), collection: customerInfo});
var customerAccount = new myApp.collection.CustomerAccount();
new myApp.views.CustomerAccount({el: $("#accountContainer"), collection: customerAccount});
}
});
And CustomerInfo and CustomerAccount views, looks like this,
myApp.views.CustomerInfo = myApp.views.MasterView.extend({
initialize: function() {
var self = this;
myApp.views.MasterView.prototype.initialize.call(self, {
qParam1: "qparam1",
qParam2: "qparam2"
});
},
render: function() {
var self = this;
self.template = _.template(myApp.Templates.get("customer-page/customer-info"));
myApp.views.MasterView.prototype.render.apply(self);
},
bindTemplate: function(data) {
var self = this;
$(self.el).html(self.template({"info": data}));
}
});
myApp.views.CustomerAccounts = myApp.views.MasterView.extend({
initialize: function() {
var self = this;
myApp.views.MasterView.prototype.initialize.call(self, {
qParam1: "qparam1"
});
},
render: function() {
var self = this;
self.template = _.template(myApp.Templates.get("customer-page/customer-accounts"));
myApp.views.MasterView.prototype.render.apply(self);
},
bindTemplate: function(data) {
var self = this;
$(self.el).html(self.template({"accounts": data}));
}
});
I would like to know if there is any way to know from the myApp.views.CustomerView
that the views CustomerInfo
and CustomerAccounts
has completed its rendering? The main problem I have here is the CustomerInfo
view loads quickly but the CustomerAccount
view takes some time to load. Hence I need to display the page on one shot, when both the views are ready on DOM.
After breaking my head for quite sometime, and searching on Google, I found this link.
So I made few changes to my MasterView and it was working and have solved the problem I had. The change I made in the MasterView is this
var activeConnections=0;
myApp.views.MasterView = Backbone.View.extend({
initialize: function(params) {
activeConnections++;
var self = this;
this.collection.fetch({
success: function(resp) {
activeConnections--;
self.collection.bind("reset", self.render(), self);
if(activeConnections===0){
// trigger the page has finished rendering
}
},
error: function(xhr, xhrStatus) {
// push error message, in case of fetch fails.
if(activeConnections===0){
// trigger the page has finished rendering
}
}
});
},
render: function() {
var self = this;
this.collection.each(function(model) {
if (model.get('authorize') && model.get('status') === "success" && model.get('data').length > 0) {
self.bindTemplate(model.get('data')[0]);
}
});
}
});
Thanks to all those who have helped me solve this.