Releases: dmytroyarmak/backbone-contact-manager
Step 9 - Edit contact page
-
Add edit buttons to contact template:
<div class="media-heading"> <h3> <%- name %> <small> <a href="#contacts/edit/<%- id %>"><span class="glyphicon glyphicon-pencil"></span></a> <a href="#contacts/delete/<%- id %>" class="delete-contract"> <span class="glyphicon glyphicon-trash"></span> </a> </small> </h3> </div>
-
Show ContactForm on #/contacts/edit/1:
router.on('route:editContact', function(id) { var contact = contacts.get(id), editContactForm; if (contact) { editContactForm = new ContactManager.Views.ContactForm({ model: contact }); $('.main-container').html(editContactForm.render().$el); } else { router.navigate('contacts', true); } });
-
To be consistent pass empty contact model on newContact route:
var newContactForm = new ContactManager.Views.ContactForm({ model: new ContactManager.Models.Contact() });
-
Show model's attributes in form:
render: function() { var html = this.template(_.extend(this.model.toJSON(), { isNew: this.model.isNew() })); this.$el.append(html); return this; },
<h2 class="page-header text-center"><%= isNew ? 'Create' : 'Edit' %> Contact</h2> ... <input type="text" class="form-control contact-name-input" value="<%- name %>"> ... <input type="email" class="form-control contact-email-input" value="<%- email %>"> ... <input type="tel" class="form-control contact-tel-input" value="<%- tel %>">
-
Update contact on form:submitted:
editContactForm.on('form:submitted', function(attrs) { contact.set(attrs); router.navigate('contacts', true); });
Step 8 - Add new contact
-
Add new contact button under contacts list:
<script type="text/template" id="tpl-contacts"> <h2 class="page-header text-center">List of contacts</h2> <p class="text-center"> <a href="#contacts/new" class="btn btn-lg btn-outline">Add Contact</a> </p> <ul class="media-list row contacts-container"></ul> </script>
-
Add Contact Form view and template
js/views/contactForm.jsContactManager.Views.ContactForm = Backbone.View.extend({ template: _.template($('#tpl-new-contact').html()), render: function() { var html = this.template(); this.$el.append(html); return this; } });
index.html:
<script src="app/js/views/contactForm.js"></script>
template:
<script type="text/template" id="tpl-new-contact"> <h2 class="page-header text-center">Create Contact</h2> <form role="form" class="form-horizontal contract-form"> <div class="form-group"> <label class="col-sm-4 control-label">Full name:</label> <div class="col-sm-6"> <input type="text" class="form-control contact-name-input"> </div> </div> <div class="form-group"> <label class="col-sm-4 control-label">Email address:</label> <div class="col-sm-6"> <input type="email" class="form-control contact-email-input"> </div> </div> <div class="form-group"> <label class="col-sm-4 control-label">Telephone number:</label> <div class="col-sm-6"> <input type="tel" class="form-control contact-tel-input"> </div> </div> <div class="form-group"> <div class="col-sm-offset-4 col-sm-3"> <button type="submit" class="btn btn-outline btn-lg btn-block">Submit</button> </div> <div class="col-sm-3"> <a href="#contacts" class="btn btn-outline btn-lg btn-block">Cancel</a> </div> </div> </form> </script>
-
Render ContactForm view on #/contacts/new route:
router.on('route:newContact', function() { var newContactForm = new ContactManager.Views.ContactForm(); $('.main-container').html(newContactForm.render().$el); });
-
Listen to form submit and trigger event with form's data:
events: { 'submit .contract-form': 'onFormSubmit' }, /* ... */ onFormSubmit: function(e) { e.preventDefault(); this.trigger('form:submitted', { name: this.$('.contact-name-input').val(), tel: this.$('.contact-tel-input').val(), email: this.$('.contact-email-input').val() }); }
-
Create new Contact on form submitted:
router.on('route:newContact', function() { var newContactForm = new ContactManager.Views.ContactForm(); newContactForm.on('form:submitted', function(attrs) { attrs.id = contacts.isEmpty() ? 1 : (_.max(contacts.pluck('id')) + 1); contacts.add(attrs); router.navigate('contacts', true); }); $('.main-container').html(newContactForm.render().$el); });
Step 7 - Delete contact button
-
Add delete link to contact's template:
<div class="media-heading"> <h3> <%- name %> <small> <a href="#contacts/delete/<%- id %>" class="delete-contract"> <span class="glyphicon glyphicon-trash"></span> </a> </small> </h3> </div>
-
Add click event handler to contact view and make console log on click:
events: { 'click .delete-contract': 'onClickDelete' }, /* ... */ onClickDelete: function(e) { e.preventDefault(); console.log('Delete'); }
-
Delete contact from collection on click:
onClickDelete: function(e) { e.preventDefault(); this.model.collection.remove(this.model); }
-
Remove view on model remove:
initialize: function() { this.listenTo(this.model, 'remove', this.remove); },
Step 6 - Add Router
-
Create js/router.js file with our router:
ContactManager.Router = Backbone.Router.extend({ routes: { '': 'home', 'contacts': 'showContacts', 'contacts/new': 'newContact', 'contacts/edit/:id': 'editContact' } });
and in index.html:
<script src="app/js/router.js"></script>
-
Instantiate router in app start method and start backbone history:
var router = new ContactManager.Router(); router.on('route:home', function() { console.log('Home'); }); router.on('route:showContacts', function() { console.log('Show contacts'); }); router.on('route:newContact', function() { console.log('New contact'); }); router.on('route:editContact', function(id) { console.log('Edit contact'); }); Backbone.history.start();
-
Redirect from home to contacts using router.navigate():
router.on('route:home', function() { router.navigate('contacts', { trigger: true, replace: true }); });
-
Show contacts only on contacts path:
router.on('route:showContacts', function() { var contactsView = new ContactManager.Views.Contacts({ collection: contacts }); $('.main-container').html(contactsView.render().$el); });
Step 5 - Render All Conracts
-
Create start method in app.js
start: function() { console.log('Contact Manager started!'); }
-
Add application initialization block in index.html:
<script> $(function() { ContactManager.start(); }); </script>
-
Check in DevTools
-
Pass bootstrapping data to start method:
<script> $(function() { ContactManager.start({ contacts: [ { id: 1, name : 'Terrence S. Hatfield', tel: '651-603-1723', email: '[email protected]' }, { id: 2, name : 'Chris M. Manning', tel: '513-307-5859', email: '[email protected]' }, { id: 3, name : 'Ricky M. Digiacomo', tel: '918-774-0199', email: '[email protected]' }, { id: 4, name : 'Michael K. Bayne', tel: '702-989-5145', email: '[email protected]' }, { id: 5, name : 'John I. Wilson', tel: '318-292-6700', email: '[email protected]' }, { id: 6, name : 'Rodolfo P. Robinett', tel: '803-557-9815', email: '[email protected]' } ] }); }); </script>
-
Create contacts model from passed data in show method and check in DevTolls
-
Create simple contacts view (views/contacts.js):
ContactManager.Views.Contacts = Backbone.View.extend({ template: _.template($('#tpl-contacts').html()), render: function() { var html = this.template(); this.$el.html(html); return this; } });
and add template to index.html:
<script type="text/template" id="tpl-contacts"> <h2 class="page-header text-center">List of contacts</h2> <ul class="media-list row contacts-container"></ul> </script>
and
<script src="app/js/views/contacts.js"></script>
-
Add class to main container and render contacts view to it on app start:
in index.html:
<div class="container"> <div class="row"> <div class="col-xs-12 main-container"> </div> </div> </div>
in js/app.js:
var contactsView = new ContactManager.Views.Contacts({ collection: contacts }); $('.main-container').html(contactsView.render().$el);
-
Add template for Contact View:
in index.html:<script type="text/template" id="tpl-contact"> <div class="thumbnail"> <img class="media-object" src="app/img/faces/<%- avatar %>"> </div> <div class="media-heading"> <h3> <%- name %> </h3> </div> <div class="media-body"> <dl> <dt>Phone Number:</dt> <dd><%- tel %></dd> <dt>Email:</dt> <dd><%- email %></dd> </dl> </div> <hr> </script>
and js/views/contact.js:
ContactManager.Views.Contact = Backbone.View.extend({ tagName: 'li', className: 'media col-md-6 col-lg-4', template: _.template($('#tpl-contact').html()), render: function() { var html = this.template(this.model.toJSON()); this.$el.append(html); return this; } });
-
Render each contact in Contacts view:
ContactManager.Views.Contacts = Backbone.View.extend({ template: _.template($('#tpl-contacts').html()), renderOne: function(contact) { var itemView = new ContactManager.Views.Contact({model: contact}); this.$('.contacts-container').append(itemView.render().$el); }, render: function() { var html = this.template(); this.$el.html(html); this.collection.each(this.renderOne, this); return this; } });
Step 4 - Simple Contact view
-
Create file
app/js/views/contact.js
with view:ContactManager.Views.Contact = Backbone.View.extend({ render: function() { var html = '<h1>' + this.model.get('name') + '</h1>'; this.$el.html(html); return this; } });
and add to index.html:
<script src="app/js/views/contact.js"></script>
-
Show in console how to render and view's root element (el)
var bob = new ContactManager.Models.Contact({name: 'Bob'}) var bobView = new ContactManager.Views.Contact({model: bob}) bobView.render() bobView.$el
-
Append view to body:
$('body').append(bobView.$el)
Step 3 - Contacts Collection
-
Add collections/contacts.js with collection:
ContactManager.Collections.Contacts = Backbone.Collection.extend({ model: ContactManager.Models.Contact });
and to index.html:
<script src="app/js/collections/contacts.js"></script>
-
Create collections with few models in DevTools and show some methods
var contacts = new ContactManager.Collections.Contacts([ { id: 1, name : 'Terrence S. Hatfield', tel: '651-603-1723', email: '[email protected]' }, { id: 2, name : 'Chris M. Manning', tel: '513-307-5859', email: '[email protected]' }, ])
Step 2 - Contact Model
-
Add app.js file with main namespace
window.ContactManager = { Models: {}, Collections: {}, Views: {} };
-
Add models/contact.js with empty model:
ContactManager.Models.Contact = Backbone.Model.extend({ });
and to index.html:
<script src="app/js/models/contact.js"></script>
-
Show initialization, accessors, toJSON in console
-
Add defaults to contact model:
defaults: { name: null, tel: null, email: null, avatar: null }
-
Add random avatar generation:
initialize: function() { this.set('avatar', _.random(1, 15) + '.jpg'); }
-
Create some method and show in DevTools
Step 1 - Add dependencies
-
Install dependencies. Execute in console:
bower install backbone jquery underscore --save
-
Add to index.html:
<script src="vendor/jquery/jquery.js"></script> <script src="vendor/underscore/underscore.js"></script> <script src="vendor/backbone/backbone.js"></script>
-
Check in DevTools
Step 0 - Initialization of project
- Execute in console to initialize project:
git clone https://github.com/dmytroyarmak/backbone-contact-manager.git
cd backbone-contact-manager
git checkout step-0
bower install
python -m SimpleHTTPServer