backbone.js doesn't fire click event on DOM element - backbone.js

I can't fire the click event on DOM element.
This is my js file: app.js. I'm pretty sure I'm missing something or doing wrong here but I can't figured out where.
var App = Backbone.View.extend({
el: $('body'),
initialize: function() {
_.bindAll(this, 'sayHello');
},
events: {
'click .link': 'sayHello'
},
sayHello: function(e) {
alert('Hello!');
}
});
var app = new App();
and this is my HTML file: index.htm.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<script type="text/javascript" src="assets/js/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="assets/js/underscore-min.js"></script>
<script type="text/javascript" src="assets/js/backbone-min.js"></script>
<script type="text/javascript" src="assets/js/app.js"></script>
</head>
<body>
Click here!
</body>
</html>

This was admittingly trickily. Think through the code logically. Your JS script is in your head.
The jQuery selector el: $('body') does not exist yet. (JavaScript executes immediately). Try doing el: 'body'.

You have to initialize your view on dom load event.
var App = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'sayHello'); // you don't need this for your code to work
},
events: {
'click .link': 'sayHello'
},
sayHello: function(e) {
alert('Hello!');
}
});
$(function(){
var app = new App({el: $("body")});
});

Related

Difficulty understanding how to pull information from model with parse and show in view

So I am helping to extend some functionality from an iOS app into a Parse/backbone style app. I am able to get information from the Parse database, but am having a difficult time understand how to render that with a view.
Here is the code I have so far
<!doctype html>
<head>
<meta charset="utf-8">
<title>My Parse App</title>
<meta name="description" content="My Parse App">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/styles.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="js/underscore.js"></script>
<script type="text/javascript" src="http://www.parsecdn.com/js/parse-1.3.0.min.js"></script>
</head>
<body>
<div id="main">
<h1 id="actual_question"></h1>
<script type="text/template" id="question">
</script>
</div>
<script type="text/javascript">
Parse.initialize("hidden-for-security", "hidden-for-security");
var Question = Parse.Object.extend("Question");
var query = new Parse.Query(Question);
query.get("fhLIwu6zst", {
success: function (Question) {
var questionText = Question.get('questionText');
alert(questionText);
},
error: function (object, error) {
alert('terrible failure');
}
});
var questionView = Parse.View.extend({
el: '#actual_question',
initialize: function() {
this.render();
},
render: function() {
this.$el.html("something");
}
});
var questionView = new questionView({});
</script>
</body>
</html>
For the query the alert shows that I have successfully pulled that information from the database. Where I have "something" in the questionView i'd like to display that same query information but am having trouble with those. What am I missing?
Create your view with model.
var questionView = new questionView({
model: query
});
In your render method you should use some templating or whatever you want.
Read here about it.
render: function() {
var compiled = _.template("Id: <%= Id %>");
this.$el.html(compiled(this.model.toJSON()));
}

Underscore templating not working for simple message with Backbone.js

Just trying to make Backbone.js display a simple message on index.html...It fails if I do try with underscore but it will append a message to the quiz_question div element if I try to do something like
questionTemplate: _.template( '<div>Hello <%= msg %></div>')
...What am I missing?
Index.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="quiz_question">
<input id="back_id" type="button" value="Back">
<input id="next_id" type="button" value="Next">
</div>
<script type="text/template" id="qtemplate"></script>
<script src="js/jquery-2.0.2.min.js"></script>
<script src="js/underscore-min.js"></script>
<script src="js/backbone-min.js"></script>
<script src="js/backbone.localStorage.js"></script>
<script src="js/questionmodel.js"></script>
<script src="js/questioncollection.js"></script>
<script src="js/questionview.js"></script>
<script src="js/app.js"></script>
<script type="text/template" id="qtemplate">
<div><%= msg %></div>
</script>
</body>
</html>
app.js
var app = app || {};
$(function() {
// Kick things off by creating the **App**.
new app.QuestionView();
});
questionview.js
var app = app || {};
app.QuestionView = Backbone.View.extend({
// Instead of generating a new element, bind to the existing skeleton of
// the App already present in the HTML.
el: '#quiz_question',
// Our template for the line of statistics at the bottom of the app.
questionTemplate: _.template( $('#qtemplate').html() ),
//questionTemplate: _.template( '<div>Hello <%= msg %></div>'),
// Delegated events for displaying new questions, and clearing existing ones
events: {
'click #back_id': 'displayPreviousQuestion',
'click #next_id': 'displayNextQuestion'
},
// The QuestionView listens for changes to its model, re-rendering. Since there's
// a one-to-one correspondence between a **Question** and a **QuestionView** in this
// app, we set a direct reference on the model for convenience.
initialize: function() {
//app.Questions.fetch();
this.render();
},
render: function(){
// render the function using substituting the varible 'who' for 'world!'.
this.$el.append(this.questionTemplate({msg: "hope floats"}));
//***Try putting your name instead of world.
},
displayPreviousQuestion: function() {
},
displayNextQuestion: function() {
}
});
Your page looks like this:
<script src="js/questionview.js"></script>
<!-- ... -->
<script type="text/template" id="qtemplate">
<div><%= msg %></div>
</script>
so questionview.js will be loaded and executed before #qtemplate is in the DOM. Inside questionview.js you have this:
app.QuestionView = Backbone.View.extend({
//...
questionTemplate: _.template( $('#qtemplate').html() ),
so _.template( $('#qtemplate').html() ) will be executed while questionview.js is being loaded and that happens before there is a #qtemplate available. The result is that you end up doing _.template(undefined) and that doesn't do anything useful.
You can wrap the view definition in a $(function() { ... }) to delay its execution until after the DOM is ready or you could delay creating the template function until you need it with something like this:
initialize: function() {
this.questionTemplate = _.template($('#qtemplate').html());
}
in your QuestionView. There are variations on those two basic approaches but that should get you started.
Above answer explain cause very well, but if you want to do quick fix, moving template tag above other script would fix the problem.

Events not fireing on click and unable to high light the dom element

I am making a Backbone.js app, in this i got the issue on the events.. and filter
issue 1:
When i click on the list item events not firing... method is not called
issue 2 : in the Students View "getScore" method not called when i am click on the 'highScoreBtn'..
request :
After i filter the high values from 'scored' - how can i high light that 'li' - to adding some class name ('.highlight)..
what is wrong with my code.. or can any one advice me the right way..
My sample JS:
$(function() {
var student = [
{name:"student0",scored:75},{name:"student1",scored:49},{name:"student2",scored:25},
{name:"student3",scored:96}, {name:"student4",scored:42}, {name:"student5",scored:85},
{name:"student6",scored:68}, {name:"student7",scored:19}, {name:"student8",scored:85},
{name:"student9",scored:26}
]
var model = Backbone.Model.extend({
defaults:{
name:"undefined",
scored:"0"
}
});
var collection = Backbone.Collection.extend({
model:model
});
var studentView = Backbone.View.extend({
tagName:'li',
className:"list",
events:{
'click .list':"called"
},
template:_.template($("#studentTemplate").html()),
render:function(){
this.$el.append(this.template(this.model.toJSON()));
return this;
},
called:function(){
alert("i a called")
}
});
var studentsView = Backbone.View.extend({
el:$(".page"),
events:{
"click #highScoreBtn":"showHighScore"
},
initialize:function(){
this.collection = new collection(student);
this.render();
},
render:function(){
var that = this;
_.each(this.collection.models, function(item){
that.$el.find('ul').append(new studentView({model:item}).render().el);
})
},
getHighSocre:function(){
return _.each(this.collection, function(item){
return item.get('scored') > 60;
})
},
showHighScore:function(){
this.getHighSocre();
}
})
var newStudentList = new studentsView();
});
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,Chrome=1" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
<title>User Manager</title>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
<style type="text/css">
li{
border-bottom:1px solid gray;
list-style: none;
padding: 10px;
}
ul{
padding:0;
margin:0;
}
li:last-child{
border: 0;
}
</style>
</head>
<body>
<div class="container">
<h1>Student Manager</h1>
<hr>
<div class="page">
<a id="highScoreBtn" class="btn btn-primary" href="#">Show high Score</a>
<hr>
<ul>
</ul>
</div>
</div>
<script id="studentTemplate" type="text/template">
<strong>Name :</strong> <%= name %> <span>Scored:</span> <%= scored %>
</script>
<script type="text/javascript" src="js/lib/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/lib/underscore-min.js"></script>
<script type="text/javascript" src="js/lib/backbone-min.js"></script>
<script type="text/javascript" src="js/student.js"></script>
</body>
</html>
for issue1:
It looks like StudentView are trying to observe itself.
View should observe DOM event of its child element.
var var studentView = Backbone.View.extend({
tagName:'li',
// className:"list", # move to template
events:{
'click .list':"called"
},
....(omitting)
<script id="studentTemplate" type="text/template">
<span class="list"><strong>Name :</strong> <%= name %> <span>Scored:</span> <%= scored %></span>
</script>
for issue2:
Are showHighScore called correctly?
if you add debug code, what is displayed in console of developer tool?
getHighSocre:function(){
console.log('getHighScore is called');
return _.each(this.collection, function(item){
return item.get('scored') > 60;
})
},
showHighScore:function(){
console.log('showHighScore is called');
var highscore = this.getHighSocre();
console.log(highscore);
}
if functions are called, you should add some codes to do something for highlighting in getHighScore function.
-- EDIT --
It may be possible by observing Backbone Model event in StudentView.
This is not a clean way too much, because model's highlight property should be set on model's initialization.
var model = Backbone.Model.extend({
defaults:{
name:"undefined",
scored:"0",
highlight:false
}
});
var studentView = Backbone.View.extend({
...
initialize: function(){
this.model.on("change", this.highlight, this);
},
...
highlight: function(){
if (this.model.get('hilight')){
$('.list', this.el).addClass("hilight");
}
}
})
var studentsView = Backbone.View.extend({
...
getHighSocre:function(){
_.each(this.collection, function(item){
if (item.get('scored') > 60){
item.set(hilight:true);
}
})
},
...
})
I am not sure, but I hope following code help you:
render:function(){
var that = this;
that.$el.find('ul').empty();
_.each(this.collection.models, function(item){
that.$el.find('ul').append(new studentView({model:item}).render().el);
})
},
showHighScore:function(){
this.getHighSocre();
this.render();
}

Underscore's bindAll: Cannot read property 'bind' of undefined

<!DOCTYPE HTML>
<html>
<head>
<title></title>
</head>
<body>
<div id="menu"></div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.0/backbone.localStorage-min.js" type="text/javascript"></script>
<script type="text/javascript">
var myView = Backbone.View.extend({
events: {
'click #menu': 'insideMenuHandler'
},
//for event click
initialize: function() {
_.bindAll(this, 'insideMenuHandler', 'outsideMenuHandler');
},
render: function() {
// Both <body> and <html> for paranoia.
$('body, html').on('click', this.outsideMenuHandler);
// ...
return this;
},
remove: function() {
// Clean up after ourselves.
$('body, html').off('click', this.outsideMenuHandler);
// ...
},
// ...
outsideMenuHandler: function(e) {
// ...
return false;
}
});
var v=new myView({el: '#view-goes-here'});
v.render();
</script>
</body>
</html>
Hey i am new to backbone.js and not understanding what is wrong in the code below, where do i change my code to make it working? Is there a problem with the bind function or something else is going wrong?
You're calling _.bindAll in the line
_.bindAll(this, 'insideMenuHandler', 'outsideMenuHandler');
but you don't have any function with name insideMenuHandler in the view.

Getting started with backbone

Amateurish this question might be but none the less could use a hand. Just got backbone out of the packaging and started the hello world example but cant seem to get it up and running. Any chance someone could tell me why Im not seeing the results of this?
(function($){
var ListView = Backbone.View.extend({
el: $(body), //attaches this.el to an existing element
initialize: function(){
_.bindAll(this, 'render'); //fixes loss of context for this within elements
this.render(); //not all views are self-rendering. This is one.
},
render: function(){
$(this.el).html("<ul><li>Hello World!</li></ul>");
}
});
var listVew = new ListView();
})(jQuery);
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> Hello Backbone </title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/underscore.js/1.1.6/underscore-min.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/backbone.js/0.3.3/backbone-min.js"></script>
<script src="backbone.js" type="text/javascript"></script>
</body>
</html>
I tried your code in a jsfiddle and got this error: Uncaught ReferenceError: body is not defined
use the string 'body' as your view's el selector
This works: http://jsfiddle.net/PeGW6/
Also note you are using a very very old version of backbone. Upgrade to the most recent build.

Resources