JSFiddle - React, Tailwind, and code Playground
by Cody Lindley
HTML
<script src="https://dl.dropboxusercontent.com/u/2026291/backbone/jquery-2.0.2.js"></script>
<script src="https://dl.dropboxusercontent.com/u/2026291/backbone/lodash.underscore.js"></script>
<script src="https://dl.dropboxusercontent.com/u/2026291/backbone/backbone.js"></script>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<small>read: <a href="http://tech.pro/tutorial/1476/part-2-backbonejs-deconstructed">Part 2: Backbone.js Deconstructed</a></small>
<h4>Contact List:</h4>
<div class="panel panel-default">
<div class="panel-body">
<ul id="contacts" class="list-unstyled"></ul>
</div>
</div>
<h4>Add Contact:</h4>
<fieldset class="form-inline" role="form">
<div class="form-group">
<input type="text" class="form-control" id="firstName" value="John" placeholder="First Name" style="width:120px;" />
</div>
<div class="form-group">
<input type="text" class="form-control" id="lastName" value="Doe" placeholder="Last Name" style="width:120px;" />
</div>
<div class="form-group">
<input type="tel" class="form-control" id="phone" value="000-000-0000" placeholder="Phone #" style="width:120px;" />
</div>
<br>
<br>
<button class="btn btn-primary btn-sm">Add</button>
</fieldset>
<hr /> <small>Disclaimer: This code is for learning about a model, collection, and view. Parts of it are pretty ugly and not optimized. Don't worry about it, just worry about grokking the Backbone.js parts which are contrived to create a stepping stone and thus written to this end.</small>
</div>
CSS
body {
margin:10px;
}
.removeContactBtn{
margin-left:10px;
}
#contacts {
margin-bottom:0px;
}
#contacts li{
margin-bottom:10px;
margin-left:10px;
display: inline-block;
}
#contacts li:last-child{
margin-bottom:0px;
}
.form-inline .form-group {
display: inline-block;
margin-bottom: 0;
vertical-align: middle;
}
JavaScript
//extend Backbone.Model and setup a Contact model class/constrcutor
var Contact = Backbone.Model.extend({
defaults: {
firstName: null,
lastName: null,
phone: null
},
getName: function () {
return this.get('firstName') + ' ' + this.get('lastName');
}
});
/*create a contacts collection, tell it which model is used for the collection, seed it with one contact model*/
var contacts = new Backbone.Collection({ //seed it with some data
firstName: 'Jane',
lastName: 'Doe',
phone: '111-111-1111'
}, {
model: Contact
});
//create a AddContactsView class, then create instance
var AddContactsView = Backbone.View.extend({
el: 'fieldset',
events: {
'click button': 'addContact'
},
addContact: function () {
var firstName = this.$('#firstName').val();
var lastName = this.$('#lastName').val();
var phone = this.$('#phone').val();
if (firstName && lastName && phone) {
contacts.add({ //this will invoke the Backbone internal 'add' event
firstName: firstName,
lastName: lastName,
phone: phone
});
this.$('input').val('');
}
}
});
var addContactsViewInstance = new AddContactsView();
//create ContactListView class, then create instance
var ContactListView = Backbone.View.extend({
el: '#contacts',
events: {
'click li button': 'removeContact'
},
initialize: function () {
this.render(); //render list
this.listenTo(contacts, 'add remove', this.render); //the magic
},
removeContact: function (e) {
$(e.target).parent('li').remove();
contacts.findWhere({
firstName: $(e.target).parent('li').find('span').text().split(' ')[0].trim(),
lastName: $(e.target).parent('li').find('span').text().split(' ')[1].trim()
}).destroy(); //this will invoke the internal 'remove' event
},
render:...