I have a backbone/marionette project structured with requirejs.
define([
'views/FormView',
'path/to/Model',
], function (FormView, Model) {
"use strict";
return FormView.extend({
model: new Model(),
/* --- rest of view stuff --- */
});
});
All the models in the project are being initialized (ie, initialize() will be called on all the models) when the page loads, but the views are only being initialized when they are instantiated by the controller.
The models should only be initalized once they are instantiated, and it's causing me a number of headaches.
Has anyone encountered this before?
Update:
thanks to Kevin and Yura for their answers, this code works:
define([
'views/FormView',
'path/to/Model',
], function (FormView, Model) {
"use strict";
return FormView.extend({
model: undefined,
initialize: function () {
this.model = new Model();
}
/* --- rest of view stuff --- */
});
});
Your problem is that
model: new Model()
runs as soon as this requirejs module is loaded into the browser. That is, when it is required, it returns the extended FormView
, and that prototype is used for all instances of FormView
.
At this time new instance object of Model
is instantiated and that same instance is used as the model
property of every new instance of FormView
.
What you can do is instead of extending your FormView
with the model
property directly, delegate that model
instance creation to initialization of the FormView
instance:
define([
'views/FormView',
'path/to/Model',
], function (FormView, Model) { "use strict";
return FormView.extend({
initialize: function(){
/* Create property `model` whenever new instance of FormView is created */
this.model = new Model();
}
/* --- rest of view stuff --- */
});
});
Here's complete working example to show the difference:
/** EXAMPLE 1 **
Directly extending with `model` property and assigning
new instance of `Model`. Later you find out same model
instance is used for all `MyView` instances.
*/
var MyView = Backbone.View.extend({
model: new Backbone.Model(),
render: function(){
this.$el.text('I am ' + this.model.get('name'));
}
});
var myView1 = new MyView();
myView1.$el.appendTo(document.body);
var myView2 = new MyView();
myView2.$el.appendTo(document.body);
myView1.model.set({name: "Joe"});
myView2.model.set({name: "Bob"});
myView1.render();
myView2.render();
/** EXAMPLE 2 **
Extending with `model` in initialize will create and assign
new instance of `model` every time `MyOtherView` instance is created.
*/
var MyOtherView = Backbone.View.extend({
initialize: function(){
this.model = new Backbone.Model();
},
render: function(){
this.$el.text('I am ' + this.model.get('name'));
}
});
var myView1 = new MyOtherView();
myView1.$el.appendTo(document.body);
var myView2 = new MyOtherView();
myView2.$el.appendTo(document.body);
myView1.model.set({name: "Alice"});
myView2.model.set({name: "Catrine"});
myView1.render();
myView2.render();
<script src='http://code.jquery.com/jquery.js'></script>
<script src='http://underscorejs.org/underscore.js'></script>
<script src='http://backbonejs.org/backbone.js'></script>