This is presented in easy to understand fashion, so enjoy reading :)
I have a backbone app which is initialised with main.js file like this:
require([
'backbone',
'app',
'models/session'
], function (Backbone, Application, SessionModel) {
//new Application();
window.App = {
session: new SessionModel()
};
new Application();
Backbone.history.start();
});
As you can see, requirejs requires 'app' as a second param.
App is just a router which looks something like this (less important parts has been removed)
define(function(require){
'use strict';
var Backbone = require('backbone'),
Header = require('views/header'),
Login = require('views/login');
var Router = Backbone.Router.extend({
initialize: function(){
this.header = new Header();
this.header.render();
},
routes: {
'login': 'showLogin'
},
showLogin: function() {
this.showView(new Login(), {requiresAuth: false});
this.header.model.set('title', 'Login');
},
showView: function(view, options) {
if(this.currentView) this.currentView.remove();
$('.content').html(view.render().$el);
this.currentView = view;
return view;
}
});
return Router;
});
The important bit here is that in the first lines I'm requiring
Header = require('views/header');
Header view requires another view in a standard way:
LogoutView = require('views/logout');
Logout view looks like this and here I come to the essence of the problem :
define(function(require){
'use strict';
var Backbone = require('backbone'),
JST = require('templates')
return Backbone.View.extend({
model: App.session,
template: JST['app/scripts/templates/logout.hbs'],
events: {
'submit form': 'logout'
},
initialize: function(){
this.listenTo(this.model, 'change', this.render)
},
render: function(){
this.$el.html(this.template(this.model.toJSON()));
return this;
},
logout: function(e){
//nothing important here
}
});
});
As you can see at the very first line after Backbone.View.extend I'm trying to define the model property of the view:
model: App.session,
which I suppose should be accessible, because I was defining the:
window.App = {
session: new SessionModel()
};
in the main.js file.
But it seems that there is a require problem, because as require is trying to get all the files in the first lines of the program:
require([
'backbone',
'app', <<--- in this line it's trying to get all the files required in the app.js
'models/session'
], function (Backbone, Application, SessionModel) {
Then I'm getting this error :
Uncaught ReferenceError: App is not defined logout.js:8
Which is exactly the line trying to get access to App global variable:
model: App.session,
That should be defined after running main.js file, but it doesn't even go that far as require is getting the files and finds not defined App variable in the LogoutView.
I can work around this problem by defining the model inside the initialize function of the view like so:
initialize: function(){
this.model = App.session;
this.listenTo(this.model, 'change', this.render)
},
But what I really want is to understand why this error is occurring and what is the best practice of creating global Models using Backbone.js and Require.js.
The list of dependencies in a define or require (the first argument in your require or the simplified wrapper you use in your other modules) tells RequireJS that it should load and interpret those modules before interpreting the current file.
Here's what happens:
require has backbone, app, models/session as dependenciesviews/logoutviews/logout is interpreted, you try to assign App.session to your view.model but that does not exist at that point and you get a App is not defined errorOne solution would be to create a singleton of your Session object and require it when you need it.
For example, let's say you have globals/session
define(['models/session'], function (SessionModel) {
return new SessionModel();
});
You would define your app as
require([
'backbone',
'app',
'globals/session'
], function (Backbone, Application, session) {
//new Application();
window.App = {
session: session
};
new Application();
Backbone.history.start();
});
and the same change in your view/logout
define(function(require){
'use strict';
var Backbone = require('backbone'),
JST = require('templates')
return Backbone.View.extend({
model: require('globals/session'),
...
});
});
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