Reputation: 5055
I've a big problem with subviews in backbone.js.
I've two views and I want to render the second one into an element of the first one.
So i defined this.el
in the second view which is referenced to a section (section#user-data) in the first view.
I create an object of the second view after first view has been rendered and if i write
alert($('#user-data').length)
before I create my object I get a 1 so it exists.
But inside the second view I get an undefined.
If I log this.el
in any method.
But if I use e.g. body for this.el
everything works as expected.
What's the reason for that?
Example:
/**
* The example of a view for profile's component
*
*
* @module Profile
* @submodule Frontend
* @class ProfileView
* @constructor
*
*/
ProfileView = Backbone.View.extend({
// The tagname wrapping the rendered content
// The template for the current view
template : _.template('COMPONENTS_VIEW_FRAME'),
/**
* The initialisation for the current view (kind of constructor)
*
* @method initialize
*/
initialize : function() {
},
/**
* The rendering process for the current view
*
* @method render
* @param {String} oLocas the data to render inside this view
*/
render : function(oLocas) {
$(this.el).html(this.template(oLocas));
return this;
}
});
/**
* The example of a view for profile's component
*
*
* @module Profile
* @submodule Frontend
* @class ProfileView
* @constructor
*
*/
ProfileSectionView = Backbone.View.extend({
// The tagname wrapping the rendered content
// The template for the current view
template : _.template('COMPONENTS_VIEW_OPTION_SECTION'),
el : $('#user-data'),
events : {
'click a.open_close_section' : 'doIt'
},
headline : 'ddd',
/**
* The initialisation for the current view (kind of constructor)
*
* @method initialize
*/
initialize : function() {
alert($(this.el).length);
},
doIt : function(event) {
alert('jo');
},
/**
* The rendering process for the current view
*
* @method render
* @param {String} eventName the name of the triggered event
*/
render : function(oLocas) {
$(this.el).html(this.template(oLocas));
return this;
}
});
// Here I start to use the first view
var oProfileView = new ProfileView();
$('#profile').html(oProfileView.render().el).fadeIn(500, function() {
$(this).removeClass('closed');
// Here I create the second view
var oProfileSectionView = new ProfileSectionView({
model : this.model
});
oProfileSectionView.render({
headline : 'XXX',
sectionrows : 'ddd'
}).el;
});
Upvotes: 2
Views: 255
Reputation: 4090
This is a little gotcha with JavaScript.
JavaScript is looking for that element when you're defining ProfileSelectionView
. So this:
ProfileSectionView = Backbone.View.extend({
// ...
el : $('#user-data'),
// ...
});
Is actually being evaluated right there in the definition of ProfileSelectionView
, not later on when you instantiate an instance of ProfileSelectionView
.
To fix this, move the defining of el
into the initialization:
ProfileSectionView = Backbone.View.extend({
// ...
// Do not define the el here. I've commented it out
// el : $('#user-data'),
// ...
initialize : function() {
this.setElement($('#user-data'));
},
// ...
});
Or even better, you can just pass the element in when creating the ProfileSelectionView
(as noted in the Backbone.js docs):
var oProfileView = new ProfileView();
$('#profile').html(oProfileView.render().el).fadeIn(500, function() {
// ...
var oProfileSectionView = new ProfileSectionView({
model : this.model,
el: $('#user-data')
});
// ...
});
By doing it this way, you don't have to define an initialize
function in ProfileSelectionView
.
Upvotes: 4