Backbone.js: View does not reflect Model change in Todo App - javascript

I've been following Addy Osmani's book Developing Backbone.js Applications, the version available online for free. As such, the first exercise is the much touted sample "Todo app", which can also be lifted from Backbone's original documentation samples.
While the app updates the view when a new entry is added to the list of things to do, I've hit an odd snafu: When I edit a list entry and press the enter button, nothing happens. The input doesn't go out of focus and the label in the entry doesn't update automatically. However, the Model does save the edited entry, because when I refresh the page, the edited entry features the change I made it to it.
I have no idea what is going on, as the view does listen to model changes.
Here's the code:
app.TodoView = Backbone.View.extend({
tagName: "li",
template: _.template($("#item-template").html()),
events:{
"dblclick label":"edit",
"keypress .edit": "updateOnEnter",
"blur .edit": "close"
},
initalize: function(){
this.listenTo(this.model, "change", this.render);
},
render: function(){
this.$el.html(this.template(this.model.toJSON()));
this.myInput = this.$(".edit");
return this;
},
edit: function(){
this.$el.addClass("editing");
this.myInput.focus();
},
close: function(){
var value = this.myInput.val().trim();
if(value) this.model.save({ title: value});
this.$el.removeClass("editing");
},
updateOnEnter: function(x){
if(x.keyCode === 13)
this.close();
}});
app.AppView = Backbone.View.extend({
el: $("#app"),
statsTemplate: _.template($("#stat-template").html()),
events:{
"keypress #newentry": "createOnEnter",
"click #clear-completed": "clearCompleted",
"click #toggle-all": "toggleAllComplete"
},
initialize: function(){
this.allCheck = this.$("#toggle-all")[0];
this.newJob = this.$("#newentry");
this.main = this.$("#main");
this.foot = this.$("#foot");
this.listenTo(app.TodoCol, "add", this.addOne);
this.listenTo(app.TodoCol, "reset", this.addAll);
this.listenTo(app.TodoCol, "change:completed", this.filterOne);
this.listenTo(app.TodoCol, "filter", this.filterAll);
this.listenTo(app.TodoCol, "all", this.render);
app.TodoCol.fetch();
console.log(app.TodoCol.toJSON());
},
addOne: function(todo){
var view = new app.TodoView({model: todo});
$("#items").append(view.render().el);
},
addAll: function(todo){
this.$("items").html("");
app.TodoCol.each(this.addOne, this);
},
filterOne: function(todo){
todo.trigger("visible");
},
filterAll: function(){
app.TodoCol.each(this.filterOne, this);
},
render: function(){
var comp = app.TodoCol.getCompleted().length;
var open = app.TodoCol.getOpen().length;
if(app.TodoCol.length){
this.main.show();
this.foot.show();
this.foot.html(this.statsTemplate({
completed: comp,
remain: open
}));
this.$("#filters li").removeClass("active")
.filter('[href="#/' + ( app.TodoFilter || '' ) + '"]')
.addClass('selected');
}else{
this.main.hide();
this.foot.hide();
}
this.allCheck.checked = !open;
},
newEntry: function() {
return {
title: this.newJob.val().trim(),
order: app.TodoCol.nextOrder(),
completed: false
};
},
createOnEnter: function(event){
if(event.which !== 13 || !this.newJob.val().trim())
return;
app.TodoCol.create(this.newEntry());
this.newJob.val("");
},
clearCompleted: function(){
_.invoke(app.TodoCol.getCompleted(), "destroy");
return false;
},
toggleAllComplete: function(){
var comp = this.allCheck.checked;
app.TodoCol.each(function(t){
t.save({ completed: comp});
});
}});
Here are the models for good measure:
app.Todo = Backbone.Model.extend({
defaults:{
title: "",
completed: false
},
toggle: function(){
this.save({completed: !this.get("completed")});
}});
app.List = Backbone.Collection.extend({
model: app.Todo,
localStorage: new Backbone.LocalStorage("todo-backbone"),
getCompleted: function(){
return this.where({completed: true});
},
getOpen: function(){
return this.where({completed: false});
},
nextOrder: function(){
if(!this.length) return 1;
return this.last().get("order") + 1;
},
comparator: function(todo){
return todo.get("order");
}});
Please help me!

Related

Issues searching backbone collection

I have this bb app that I'm trying to search and return the results of the search, then when cleared, so all results again. I was able to get everything to show before adding the search feature, but now nothing showing up. I think the collection isn't available at the time it's trying to populate, but can't seem to get it to wait. I've tried moving the fetch around to no avail. Any help would be greatly appreciate. For the sake of ease, I've put everything in a fiddle that can be found here...
//Campaign Model w defaults
app.model.Campaign = Backbone.Model.extend({
default: {
title: '',
img: '',
id: '',
slug: '',
image_types: 'small',
tagline: ''
}
});
//Campaign Collection from model
app.collection.Campaign = Backbone.Collection.extend({
//our URL we're fetching from
url: 'https://api.indiegogo.com/1/campaigns.json?api_token=e377270bf1e9121da34cb6dff0e8af52a03296766a8e955c19f62f593651b346',
parse: function(response) {
console.log('parsing...');
return response.response; //get array from obj to add to collection based on model
},
currentStatus: function(status){
return _(this.filter(function(data){
console.log('currentStats', status);
return data.get('_pending') == status;
}));
},
search: function(searchVal) {
console.log('search...');
if (searchVal == '') {
return this;
}
var pattern = new RegExp(searchVal, 'gi');
return _(this.filter(function(data) {
return pattern.test(data.get('title'));
}));
}
});
app.collection.campaigns = new app.collection.Campaign();
app.collection.campaigns.fetch({
success: function(){
console.log('Success...');
var sHeight = window.screen.availHeight - 200 + 'px';
$('#container ul').css('height', sHeight);
},
error: function() {
console.log('error ',arguments);
}
});
//List view for all the campaigns
app.view.CampaignList = Backbone.View.extend({
events: {
'keyup #searchBox': 'search'
},
render: function(data) {
console.log('campaignList',$(this.el).html(this.template));
$(this.el).html(this.template);
return this;
},
renderAll: function(campaigns) {
console.log('campList renderAll', campaigns, $('#campaignList'));
$('#campaignList').html('');
campaigns.each(function(campaign){
var view = new app.view.CampaignItem({
model: campaign,
collection: this.collection
});
console.log(view);
$('#campaignList').append(view.render().el);
});
return this;
},
initialize: function() {
console.log('init campList',app);
this.template = _.template($('#campaignList-tmp').html());
this.collection.bind('reset', this.render, this);
},
search: function(e) {
console.log('listView search');
var searchVal = $('#searchBox').val();
this.renderAll(this.collection.search(searchVal));
},
sorts: function() {
var status = $('#campSorting').find('option:selected').val();
if(status == '') {
status = false;
};
this.renderAll(this.collection.currentStatus(status));
}
});
//Item view for single campaign
app.view.CampaignItem = Backbone.View.extend({
events: {},
render: function(data){
console.log('campItem render...', data);
this.$el.html(this.template(this.model.toJSON()));
return this;
},
initialize: function(){
console.log('campItem init');
this.template = _.template( $('#campaignItem-tmp').html());
}
});
//Router
app.router.Campaign = Backbone.Router.extend({
routes: {
'': 'campaigns'
},
campaigns: function(){
this.campListView = new app.view.CampaignList({
collection: app.collection.campaigns
});
$('#container').append(this.campListView.render().el);
this.campListView.sorts();
}
});
app.router.campaigns = new app.router.Campaign();
Backbone.history.start();
http://jsfiddle.net/skipzero/xqvrpyx8/

Backbone.Js app reloading, calling render twice

I've extended the Backbone version of todomvc and am finding the views very fickle. Hard getting listeners and events disambiguated. Cannot see why this calls app.AppView.render() render twice, and on the second call the items in local storage are dropped. Anyone had issues with local Backbone storage?
A search input stores the first item, then something reloads and the collection is empty.
The Html View:
app.AppView = Backbone.View.extend({
el: '#searchapp',
events: {
'keypress #new-search': 'createOnEnter',
'click #clear-unstarred': 'clearUnStarred',
},
initialize: function () {
this.$input = this.$('#new-search');
this.$list = $('#search-list');
this.$results = this.$('#search-grids');
this.$stats = this.$('#search-stats');
this.listenTo(app.searches, 'add', this.addOne);
this.listenTo(app.searches, 'reset', this.addAll);
this.listenTo(app.searches, 'change:starred', this.filterOne);
this.listenTo(app.searches, 'filter', this.filterAll);
this.listenTo(app.searches, 'all', this.render);
app.searches.fetch(); //{reset: true}
},
render: function () {
//app.SearchFilter = app.SearchFilter || 'starred';
var starred = app.searches.starred().length;
var remaining = app.searches.remaining().length;
if (app.searches.length) {
var h = $('#stats-template').html(), t = _.template(h),
d = {
count: (starred + remaining),
starred: starred,
remaining: remaining
}, s = t(d);
this.$stats.html(s);
this.$('#filters a').removeClass('selected').filter('[href="#/' + (app.SearchFilter || '') + '"]').addClass('selected');
app.searches.last().trigger('runsearch');
} else {
//this.$results.hide();
//this.$stats.hide();
}
}, ...............
The View for Items:
app.SearchView = Backbone.View.extend({
tagName: 'div',
events: {
'click .do-search': 'runSearch',
'click .do-destroy': 'clear',
'click .do-toggle-star': 'togglestar',
'dblclick label': 'edit',
'keypress input.title': 'updateOnEnter',
'keydown input.title': 'revertOnEscape',
'blur input.title': 'close'
},
initialize: function () {
this.$results = $('#search-grids');
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'destroy', this.remove);
this.listenTo(this.model, 'visible', this.toggleVisible);
this.listenTo(this.model, 'runsearch', this.runSearch);
},
render: function () {
if (this.model.changed.id !== undefined) {
return;
}
var h = $('#search-item-template').html(), t = _.template(h),
d = this.model.toJSON(), s = t(d);
this.$el.html(s);
this.$el.toggleClass('starred', this.model.get('starred'));
this.$input = this.$('input.title');
this.toggleVisible();
return this;
},
`
Chrome developer tools wasn't showing "Storage" during issue. Cleanup did help. Haven't made significant changes. Essentially made sure to do the collection add() and model save() here --
http://www.mostlystatic.com/2013/01/26/minimal-backbone-localstorage-example.html

Validate models with Backbone.js

with help of books and tutorials im trying to do my own Todo list app. My problem is that when you add ah todo my model should validate if the input come with some text before rendering. i created the validate methis but it doesnt work and i dont know how to track the error, i'll appreciate if you guys could help me finding my error
Model:
var Task = Backbone.Model.extend({
validate: function(attrs){
if(!attrs.title){
return "The task has no title";
}
}
});
var task = new Task;
Collection:
var Tasks = Backbone.Collection.extend({
model: Task
});
var tasks = new Tasks([
{
title: 'my task'
},
{
title: 'my task 1'
},
{
title: 'my task 2'
},
{
title: 'my task 3'
}
]);
Views:
var TaskView = Backbone.View.extend({
tagName: "li",
template: _.template( $('#task').html() ),
initialize: function(){
this.model.on("change", this.render, this);
},
render: function(){
var template = this.template( this.model.toJSON() );
this.$el.html( template );
return this;
},
events: {
'click .icon-checkbox': 'toggleState'
},
toggleState: function(e){
var $checkbox = $(e.target);
$checkbox.toggleClass('icon-checkbox-unchecked');
}
});
var TasksView = Backbone.View.extend({
el: '#tasks',
initialize: function(){
this.render();
this.collection.on('add', this.addOne, this);
},
render: function(){
this.collection.each(this.addOne, this);
return this;
},
addOne: function(task){
var taskView = new TaskView({ model: task });
this.$el.append( taskView.render().el );
}
});
var AddTask = Backbone.View.extend({
el: '#todos',
events:{
'click #add': 'addTask'
},
addTask: function(){
var taskTitle = $('#inputTask').val();
$('#inputTask').val("");
var task = new Task( {title: taskTitle} ); // create the task model
this.collection.add(task); //add the model to the collection
}
});
var tasksView = new TasksView( {collection: tasks} );
var addTask = new AddTask( {collection: tasks} );
Edit:
I just realized that the validate methos its on ly called when you set or save info in the model, but actually what i want to do is check when the user submit a todo that if it comes with text or ini order to create and render the model.
You never actually call the validate() method. Have you looked into the Backbone Validation plugin? Works pretty slick.
https://github.com/thedersen/backbone.validation
So i came up with this solution, I am not sure if this is a good practice or not or it the view should to this but what i did is: Once you push on the add task button the addTask methos first check if the input has text or not, if it doesnt have text it just only change the placeholder to: "Todo's can not be empty" and doesnt create a model and render its view. But, if the input has text it creates the model append it to the colelction and render the view!.
Here is the new code for the view, i hope someone could tellme if this is good or if the model should validate this or any other object should to this labor.
Code:
var AddTask = Backbone.View.extend({
el: '#todos',
events:{
'click #add': 'addTask'
},
addTask: function(){
var taskTitle = $('#inputTask').val();
$('#inputTask').val(""); //clear the input
if($.trim(taskTitle) === ''){
this.displayMessage("Todo's can not be empty");
}else{
var task = new Task( {title: taskTitle} ); // create the task model
this.collection.add(task); //add the model to the collection
}
},
displayMessage: function(msg){
$('#inputTask').attr("placeholder", msg);
}
});

Backbone Sorting and Updating a listview after an action

i am trying to make my first backbone app, and have run into a problem that i just cant solve..
I have a list of links, each link has a counter next to it,
when i click on a link i want the counter to increment by 1. (i have made this, and it is working)
Next i want the link i clicked to move up in the list IF the counter value is higher than the link above.
like this.
first link (4)
second link (3)
third link (3) <-- if i click on this link i want it to move up above second link.
I have tried using comparator and sortBy, but each time i try something i just cant seem to re-render the view and also have the link move up one spot.
I did manage to sort the list initially, when the main view is initialized.
But updating the view and list placement after i click one of the links i cant figure out how to accomplish.
my code:
(function() {
window.App = {
Models: {},
Collections: {},
Views: {}
};
window.template = function(id) {
return _.template( $('#' + id).html() );
};
//Modellen
App.Models.Task = Backbone.Model.extend({
defaults: {
name: 'Foo Bar Baz',
uri: 'http://www.google.com',
counter: 0
},
validate: function(attr) {
if ( ! $.trim(attr.name) ) {
return 'En opgave kræver en title.';
};
}
});
//Collection
App.Collections.Tasks = Backbone.Collection.extend({
model: App.Models.Task,
comparator: function(task) {
return task.get('counter');
},
});
//Singel view
App.Views.TaskView = Backbone.View.extend({
tagName: 'li',
template: template('Tasks'),
initialize: function() {
this.model.on('change', this.render, this);
this.model.on('destroy', this.remove, this);
},
events: {
'click .edit' : 'retTask',
'click .delete' : 'destroy',
'click .uriLink' : 'addCounter'
},
retTask: function() {
var newTaskNavn = prompt('Hvad skal det nye navn være', this.model.get('name'));
if ( !newTaskNavn ) return;
this.model.set('name', newTaskNavn);
},
destroy: function() {
this.model.destroy();
},
addCounter: function(e) {
e.preventDefault();
var newCounter = this.model.get('counter');
this.model.set('counter', newCounter + 1);
},
remove: function() {
this.$el.remove();
},
render: function() {
this.$el.html(this.template(this.model.toJSON()) );
return this;
}
});
//Collection View
App.Views.TasksView = Backbone.View.extend({
tagName: 'ul',
initialize: function() {
this.collection.on('add', this.addOne, this);
this.render();
},
render: function() {
this.collection.each(this.addOne, this);
return this;
},
addOne: function(task) {
var taskView = new App.Views.TaskView({ model: task });
this.$el.append(taskView.render().el);
}
});
App.Views.AddTask = Backbone.View.extend({
el: '#addTask',
initialize: function() {
},
events: {
'submit' : 'submit'
},
submit: function(e) {
e.preventDefault();
var taskNavn = $(e.currentTarget).find('.navnClass').val(),
uriNum = $(e.currentTarget).find('.uriClass').val();
if ( ! $.trim(taskNavn)) {
var test = prompt('opgaven skal have et navn', '');
if ( ! $.trim(test)) return false;
taskNavn = test;
}
if( uriNum.indexOf( "http://" ) == -1 ) {
addedValue = 'http://',
uriNum = addedValue + uriNum;
}
$(e.currentTarget).find('input[type=text]').val('').focus();
//var task = new App.Models.Task({ name: taskNavn, uri: uriNum });
this.collection.add({ name: taskNavn, uri: uriNum });
}
});
// new tasks collection
var tasks = new App.Collections.Tasks([
{
name: 'Foo',
uri: 'www.google.com',
counter: 3
},
{
name: 'Bar',
uri: 'http://google.com',
counter: 2
},
{
name: 'Baz',
uri: 'http://www.google.com',
counter: 1
}
]);
// tasks.comparator = function(task) {
// return task.get("counter");
// };
tasks.sort();
// new collection view (add)
var addTaskView = new App.Views.AddTask({ collection: tasks});
// new collection view
var tasksView = new App.Views.TasksView({ collection: tasks });
$('.tasks').html(tasksView.el);
})();
My HTML: (if someone wanna try to replicate the scenario :)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>LinkList</title>
</head>
<body>
<h1>Mine opgaver</h1>
<form action="" id="addTask">
<input class="navnClass" type="text" placeholder="Link name"><input clas s="uriClass" type="text" placeholder="www.url-here.com">
<button class="nyOpgave">Ny opgave</button><br />
</form>
<div class="tasks">
<script type="text/template" id="Tasks">
<span class="linkNavn"><%= name %></span> - <%= uri %> : [<span class="counterClass"><%= counter %></span>] <button class="edit">Edit</button> <button class="delete">Delete</button>
</script>
</div>
<script src="js/underscore.js"></script>
<script src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script src="js/jquery.js"></script>
<script src="js/backbone.js"></script>
<script src="main.js"></script>
</body>
</html>
can anyone please help me figure this one out ?
/Cheers
Marcel
Okay , i have created the application for you , as you have intended it to run.I'm going to try and explain you the entire code , what i have written and why i have written.
First , take a look at the JSfiddle : here
Next , let me explain :
1.This is my model that stores the name of the link , href , the id(not used in my example but its just good practise to assign a unique id to each model) and finally the number of clicks to a link(model).
var myModel = Backbone.Model.extend({
defaults:{
'id' : 0,
'name' : null,
'link' : '#',
'clicks' : 0
}
});
2.This the collection , that stores all my models , i have added a comparator function so that when ever you add a model to a collection , it will sort the collection.
Note : i have added a - sign to sort the collection in descending order of clicks (link with maximum click to appear first)
var myCollection = Backbone.Collection.extend({
model: myModel,
comparator: function(item) {
return -item.get('clicks');
}
});
3.Now this is my main view , what do i mean main view ? This view does the main rendering of the list , that you want to show.Pretty self explanatory code here.One thing , the this.coll.bind('add change',this.render,this) , i have added a 'change' because whenever any of the models in this collection change , we want to re-render the entire list , this happens when i change the count of any link , on clicking it , i want to re-render the entire list.
var myView = Backbone.View.extend({
el: $("#someElement"),
tagName : 'ul',
initialize: function() {
this.coll = new myCollection();
this.coll.bind('add change',this.render,this);
},
events: {
"click #add": "add"
},
add: function(e){
e.preventDefault();
var mod = new myModel();
var name = $('#name').val();
var link = $('#link').val();
mod.set({'id':mod.cid, 'name':name,'link':link});
this.coll.add(mod);
},
render : function(){
$('#list').empty();
this.coll.sort();
this.coll.forEach(function(model){
var listItem = new printView({ model: model});
$('#list').append(listItem.render().el);
});
}
});
4.This is my sub-view , why do i ever make a second view , why isnt 1 view sufficient ?
Well this consider a scenario, with every link you have a delete button (for instance) when i click the delete button (and i have just 1 view) how do i identify which model to destroy(remove from collection ? ) , 1 possible way would be to associate a cid with each model and then on click i can do a this.coll.getByCid() , but this isnt such a good way to do it , IMHO , so i created a separate view for each model.This View renders each model and returns nothing more.
var printView = Backbone.View.extend({
tagName: 'li',
initialize : function(options) {
_.bindAll(this, "render");
},
events:{
"click a": "count"
},
render:function(){
var linkName = this.model.get("name");
var link= this.model.get("link");
var clicks = this.model.get("clicks");
this.$el.append("<a class='link' href='"+link+"'>"+linkName+"</a> ("+clicks+")");
return this;
},
count:function(e){
e.preventDefault();
e.stopPropagation();
var clicks = this.model.get("clicks");
clicks++;
this.model.set({'clicks':clicks});
}
});
5.Initializing my (main) myView
new myView();
Note: I do believe that this application/code can be written in much better way , with several improvements but with my calibre and with the fact that it works ( :p ) i think it can help you.
The collection comparator is only executed when new models are added to the collection: it doesn't update the collection order when properties change. In order to achieve this, you need to call collection.sort():
App.Collections.Tasks = Backbone.Collection.extend({
model: App.Models.Task,
initialize: function() {
this.on('change:counter', this.sort);
},
comparator: function(task) {
return task.get('counter');
}
});
In the list view you can listen to the collection's sort event, and re-render your view:
App.Views.TasksView = Backbone.View.extend({
tagName: 'ul',
initialize: function() {
this.collection.on('add', this.addOne, this);
this.collection.on('sort', this.render, this);
this.render();
},
render: function() {
//if there are existing child views, remove them
if(this.taskViews) {
_.each(this.taskViews, function(view) {
view.remove();
});
}
this.taskViews = [];
this.collection.each(this.addOne, this);
return this;
},
addOne: function(task) {
var taskView = new App.Views.TaskView({ model: task });
this.$el.append(taskView.render().el);
//keep track of child views
this.taskViews.push(taskView);
}
});

backbone view render not creating

Just beginning with backbone and after few hours can't seem to get even a view render working correctly. I've included all appropriate JavaScript files in HTML. Here is my script:
(function($) {
// MODELS
var Paper = Backbone.Model.extend ({
defaults : {
title : null,
author: null,
}
});
// COLLECTIONS
var PaperCollection = Backbone.Collection.extend({
model : Paper,
initialize : function() {
console.log("We've created our collection");
}
});
// VIEWS
var PaperView = Backbone.View.extend({
tagName:'li',
className: 'resultTable',
events: {
'click .ptitle':'handleClick'
},
initialize: function() {
_.bindAll(this, 'render', 'handleClick');
},
render: function() {
$(this.el).html('<td>'+this.model.get('title')+'</td>');
return this; // for chainable calls
},
handleClick: function() {
alert('Been clicked');
}
});
var ListView = Backbone.View.extend({
events: {
//"keypress #new-todo": "createOnEnter",
},
initialize : function() {
console.log('Created my app view');
_.bindAll(this, 'render', 'addOne', 'appendOne');
this.collection = new PaperCollection();
this.collection.bind('add', this.appendOne); // collection event binder
this.counter = 0;
this.render();
},
render : function() {
console.log('Render app view');
$(this.el).append("<button id='add'>Add list item</button>");
$(this.el).append("<p>More text</p>");
// $(this.el).append("<ul></ul>");
/*
_(this.collection.models).each(function(item){ // in case collection is not empty
appendOne(item);
}, this); */
},
addOne: function() {
this.counter++;
var p = new Paper();
p.set({
title: "My title: " + this.counter // modify item defaults
});
this.collection.add(p);
},
appendOne: function(p) {
var paperView = new PaperView({
model: p
});
$('ul', this.el).append(paperView.render().el);
}
});
var App = new ListView({el: $('paper_list') });
// App.addOne();
})(jQuery);
Note not getting any errors in console on FF - but still not displaying any of the render outputs in AppView). Appreciate any help. Simple HTML:
<body>
<div class="container_16">
<div class="grid_16">
<div id="paper_list">
Text...
<ul class="thelist"></ul>
</div>
</div>
<div class="clear"></div>
</div>
</body>
This will at least get you rendering the ListView...
// MODELS
var Paper = Backbone.Model.extend ({
defaults : {
title : null,
author: null,
}
});
// COLLECTIONS
var PaperCollection = Backbone.Collection.extend({
model : Paper,
initialize : function() {
console.log("We've created our collection");
}
});
// VIEWS
var PaperView = Backbone.View.extend({
tagName:'li',
className: 'resultTable',
events: {
'click .ptitle':'handleClick'
},
initialize: function() {
_.bindAll(this, 'render', 'handleClick');
},
render: function() {
$(this.el).html('<td>'+this.model.get('title')+'</td>');
return this; // for chainable calls
},
handleClick: function() {
alert('Been clicked');
}
});
var ListView = Backbone.View.extend({
el: '#paper_list',
events: {
"click #add": "createOnEnter",
},
initialize : function() {
console.log('Created my app view');
_.bindAll(this, 'render', 'addOne', 'appendOne');
this.collection = new PaperCollection();
this.collection.bind('add', this.appendOne); // collection event binder
this.counter = 0;
this.render();
},
render : function() {
console.log(this);
$(this.el).append("<button id='add'>Add list item</button>");
$(this.el).append("<p>More text</p>");
// $(this.el).append("<ul></ul>");
/*
_(this.collection.models).each(function(item){ // in case collection is not empty
appendOne(item);
}, this); */
},
addOne: function() {
this.counter++;
var p = new Paper();
p.set({
title: "My title: " + this.counter // modify item defaults
});
this.collection.add(p);
},
appendOne: function(p) {
var paperView = new PaperView({
model: p
});
$('ul', this.el).append(paperView.render().el);
}
});
$(function(){
var App = new ListView();
});
A couple of things...First, I initialized your ListView inside of a document.ready to make sure that the DOM was ready to go, second, I made the el in the listview simply #paper_list then you can do $(this.el) later.
I at least got the button and "more text" to show up...Let me know if that helps!

Categories

Resources