I’m trying to use Backbone with requirejs, which is working just fine so far and I used a very clean boilerplate, but now I also want to start using Backbone’s way of handling views and models, which I haven’t before, and my lobby table view renders just fine on page load, but as soon as I change page and come back to it, it won’t render anything. No error’s given and the collection seems to fetch the new data just fine. Could it have anything to do with rendering the basic table structure in the main.js and then afterwards creating a child view in views/play.js without telling the parent view?
Backbone router (main.js)
play: function() {
var view = new app.Views.Play();
app.instance.changePage(view);
require(['controllers/play'], function(PlayController) {
PlayController.init();
});
},
…
app.Views.App = app.Extensions.View.extend({
el: 'body',
changePage: function(view) {
var previous = this.currentPage || null;
var next = view;
if(previous) {
if(AppLib.transitions === "notransitions") previous.remove();
previous.transitionOut(function() {
previous.remove();
});
}
next.render({ page: true });
this.$el.append(next.$el);
next.transitionIn();
this.currentPage = next;
// Change page title
var title = app.lang.get(next.className + ".title");
if(title === next.className + ".title") title = next.className;
document.title = (!_.isEmpty(Backbone.history.getFragment()) ? title.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}) : AppLib.name);
}
});
…
app.Views.Play = app.Extensions.View.extend({
className: 'play',
addHeader: function() {
var options = { className: "gl-header", fixed: true, elements: ['BackButton', 'LoginButton'] };
var n = new app.Views.Header({ el: "." + this.className, parentView: this, options: options });
this.$el.prepend(n.render());
},
render: function() {
var template = _.template($('script[name=play]').html());
this.$el.html(template());
this.addHeader();
return app.Extensions.View.prototype.render.apply(this, arguments);
}
});
The play controller (controllers/play.js)
define(['jquery', 'backbone', 'models/play', 'views/play'], function($, Backbone, Model, View) {
return {
init: function() {
var LobbyCollection = new Model.LobbyCollection();
LobbyCollection.getMatches();
var LobbyView = new View.Lobby({ collection: LobbyCollection });
}
}
});
The play model (models/play.js)
define(['jquery', 'backbone', 'persist', 'AppLib'], function($, Backbone, Persist, AppLib) {
var Match = Backbone.Model.extend({});
var LobbyCollection = Backbone.Collection.extend({
model: Match,
url: "/api/v1/play/lobby-updates",
initialize: function() {
},
getMatches: function(callback) {
var self = this;
this.fetch({
reset: true,
success: function(collection, response, options) {
self.trigger('successOnFetch');
},
error: function(collection, response, options) {
self.trigger('errorOnFetch');
}
});
},
parse: function(response) {
var obj = response["lobby_matches"];
this.RandomLobbyName = response["random_name"];
return _.map(obj, function(value, key) {
return obj[key];
});
}
});
return {
LobbyCollection: LobbyCollection
}
});
The play view (views/play.js)
define(['jquery', 'backbone', 'persist', 'AppLib', 'jquery_debounce'], function($, Backbone, Persist, AppLib) {
var LobbyView = Backbone.View.extend({
el: **$(".play.page-container .table")** !!".play.page-container .table",
initialize: function() {
var self = this;
this.listenTo(this.collection, 'reset', this.render);
this.listenTo(this.collection, 'successOnFetch', this.handleSuccess);
this.listenTo(this.collection, 'errorOnFetch', this.handleError);
$(".play.page-container .table button.refresh-list").on("click", $.throttle(2000, function() {
$(this).html($("<span\>", { "class": "opaque blue throbber small" })).addClass("selected").prop("disabled", true);
self.collection.getMatches();
}));
},
handleSuccess: function(options) {
setTimeout(function() {
$(".play.page-container .table button.refresh-list").removeClass("selected").removeAttr("disabled").html($("<span\>", { "class": "icon-spinner6" }));
}, 2000);
},
handleError: function(options) {
},
render: function() {
var template = _.template($('script[name=lobby-table]').html());
var $tbody = this.$el.children("tbody");
$tbody.children().not(".create-lobby").remove();
$tbody.append(template({ collection: this.collection.toJSON() }));
return this;
}
});
return {
Lobby: LobbyView
}
});
I solved it myself. The problem was I looked up how to make a view on here and they defined the element using jquery so: el: $("selector") and I followed that, but that’s wrong. Backbone already puts it into jquery itself, so it’s double that way. So I simply put my selector in quotation marks and now everything works.