Reputation: 5854
I am trying to play around with Backbone and have trouble with Views, in particular with "el" and events. I noticed I'm not the first one, but unfortunatelly could not find an optimal answer to my questions.
My base relevant code:
HTML:
<!DOCTYPE html>
<html>
<head>
<script data-main="main" src="js/require.js"></script>
</head>
<body>
<div id="login"></div>
</body>
</html>
VIEW:
var view = Backbone.View.extend({
el: $("#login"),
initialize: function() {
this.el.html('<div>click here</div>'); // TypeError: this.el.html is not a function
}
.....
Question 1:
Please note the comment in the initialize() function, that's error registered by Firebug when I load this code.
But, when I only remove the "el" config and instead put the corresponding assignement in initialize() the run-time error is gone!
var view = Backbone.View.extend({
// "el" is now removed
initialize: function() {
this.el = $("#login"); // explicit assignement
this.el.html('<div>click here</div>'); // appends the div correctly
}
.....
Question 2: In both of these examples if I specify events in View's events config, the event never fires:
events: {
"click": "tryLogin"
},
...
Please enlighten me! :)
Upvotes: 0
Views: 1773
Reputation: 239250
The specific problem you're having is that this.el
is not a jQuery object, and it has no .html
method. That's what this.$el
is for; this.el
is a raw DOM element and this.$el
is the jQuery-wrapped version of that object. You should not overwrite el
with a jQuery-selected element.
The real problem you're having is that you're trying to modify the DOM in initialize
.
If, in initialize
, you want to access a DOM element that is already in the DOM, you need to pass an el:
option to the view's constructor. Generally you shouldn't do this though. Your view should do its DOM manipulation in its render
method.
From the docs:
If you'd like to create a view that references an element already in the DOM, pass in the element as an option:
new View({el: existingElement})
In practice I've found that el
and $el
are still available, but you should avoid using them in initialize
regardless. Stick to modifying the DOM in render
, which is specifically where your view's "drawing" code is meant to go:
var view = Backbone.View.extend({
el: '#login',
render: function () {
this.$el.append('<h1>What!</h1>');
return this;
}
});
$(function () {
new view().render();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>
<div id="login"></div>
In regards to Question 2, I cannot reproduce your problem. The following works exactly as expected:
var View = Backbone.View.extend({
el: '#login',
events: {
'click': 'onClick'
},
onClick: function () {
alert('click!');
},
render: function () {
this.$el.append('<h1>What!</h1>');
}
});
new View().render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>
<div id="login"></div>
Upvotes: 2