Backbone

2,373 views

Published on

Backbone.js helps structure you javascript application code in a scalable way.
In this keynote I demonstrate how to use it in a simple walk-through example, and discuss the advantages of using an MVC framework.

Published in: Technology, Business
1 Comment
5 Likes
Statistics
Notes
No Downloads
Views
Total views
2,373
On SlideShare
0
From Embeds
0
Number of Embeds
393
Actions
Shares
0
Downloads
105
Comments
1
Likes
5
Embeds 0
No embeds

No notes for slide

Backbone

  1. 1. Backbone.js How to write a well structured multi page web application Thursday, September 12, 13
  2. 2. About • Ynon Perek • ynon@ynonperek.com • Find and download slides from: http://ynonperek.com Thursday, September 12, 13
  3. 3. Unstructured JS • Developer Starts writing JS code • App gets big, developer gets angry Thursday, September 12, 13
  4. 4. What We Want • Build apps like lego • Everything has a place Thursday, September 12, 13
  5. 5. JS Solution • Separate Logic from View • Use a framework Thursday, September 12, 13
  6. 6. MV* Frameworks Model View * Thursday, September 12, 13
  7. 7. Available JS MV* • And a lot more... • Nice comparison: http://todomvc.com/ Thursday, September 12, 13
  8. 8. Backbone.js • Created by Jeremy Ashkenas • Goal: Keep your code AWAY from the DOM Thursday, September 12, 13
  9. 9. Reasons Why • Well tested and proven • Strong community • Simple: Almost no magic Thursday, September 12, 13
  10. 10. Who’s Using Backbone ? Big list: http://backbonejs.org Thursday, September 12, 13
  11. 11. Backbone (MV*) Concepts Thursday, September 12, 13
  12. 12. Application Structure • Each “page” is just a div • “Page” can be a full page or partial <body>   <div class="page">     <h1>About Page</h1>   </div>   <div class="page">     <h1>Main Page</h1>   </div>   <div class="page">     <h1>Item Info</h1>   </div>   </body> Thursday, September 12, 13
  13. 13. Application Structure • Navigating in the app is just calling a route function • Route function slides divs in-and-out help: function() {   alert('What can I help you with ?'); } Thursday, September 12, 13
  14. 14. Application Structure • Implementing Client-side logic • Models “know” • Views “show” Thursday, September 12, 13
  15. 15. Application Structure Model View DOM Store Data Renders Data Thursday, September 12, 13
  16. 16. Models • Models store your data • Models have no visual representation • Functionality for managing changes Thursday, September 12, 13
  17. 17. Views • A View provides the visual representation of a model Task Model Thursday, September 12, 13
  18. 18. Collections • Models are usually grouped in collections * Task Model * Task Model * Task Model Daily Tasks Walk the dog Water the plans Thursday, September 12, 13
  19. 19. Backbone Benefits • Good separation of concerns • Best for large client- side applications Thursday, September 12, 13
  20. 20. What Backbone Is Not • It’s not a framework • So it’s ok to use only parts of it Thursday, September 12, 13
  21. 21. What Backbone Is Not • It’s not for small apps that just “show data” • Backbone assumes client-side logic Thursday, September 12, 13
  22. 22. What Backbone Is Not • It will never get in your way :) Thursday, September 12, 13
  23. 23. Coding Time Thursday, September 12, 13
  24. 24. Todo App • Model for each task • View for each task • Main application view Thursday, September 12, 13
  25. 25. Task Model (function(global) {       global.models.Task = Backbone.Model.extend({         defaults: {             completed: false,             text: ''         }     });   }(this)); Thursday, September 12, 13
  26. 26. Task Model (function(global) {       global.models.Task = Backbone.Model.extend({         defaults: {             completed: false,             text: ''         }     });   }(this)); Define a new model Thursday, September 12, 13
  27. 27. Task Model (function(global) {       global.models.Task = Backbone.Model.extend({         defaults: {             completed: false,             text: ''         }     });   }(this)); Set default values Thursday, September 12, 13
  28. 28. Task View     global.views.TaskView = Backbone.View.extend({         tagName: "div",         className: "task",         events: {             "click" : "handle_click"         }, Define a new View Thursday, September 12, 13
  29. 29. Task View     global.views.TaskView = Backbone.View.extend({         tagName: "div",         className: "task",         events: {             "click" : "handle_click"         }, Specify HTML element Thursday, September 12, 13
  30. 30. Task View     global.views.TaskView = Backbone.View.extend({         tagName: "div",         className: "task",         events: {             "click" : "handle_click"         }, Define Event Handlers name of a method that will be called when the view is clicked Thursday, September 12, 13
  31. 31. View Rendering • render() method of a view is used to render it to HTML • Usually implemented with client side template engine Thursday, September 12, 13
  32. 32. Task View         render: function() {             this.$el.html( this.template( this.model.toJSON()));             return this;         },         template: Handlebars.compile($('#task-template').html()) Define Render Function Thursday, September 12, 13
  33. 33. Task View         render: function() {             this.$el.html( this.template( this.model.toJSON()));             return this;         },         template: Handlebars.compile($('#task-template').html()) Paint The View onto HTML Thursday, September 12, 13
  34. 34. Task View         render: function() {             this.$el.html( this.template( this.model.toJSON()));             return this;         },         template: Handlebars.compile($('#task-template').html()) Handlebars is used as a template engine Thursday, September 12, 13
  35. 35. Task View         initialize: function(opts) {             this.model.on('change', this.render, this );         },         handle_click: function() {             if ( this.model.get('completed') ) {                 this.model.set('completed', false);             } else {                 this.model.set('completed', true);             }         }, initialize is called from a view’s constructor Thursday, September 12, 13
  36. 36. Task View         initialize: function(opts) {             this.model.on('change', this.render, this );         },         handle_click: function() {             if ( this.model.get('completed') ) {                 this.model.set('completed', false);             } else {                 this.model.set('completed', true);             }         }, We use it to bind event handlers on the model Thursday, September 12, 13
  37. 37. Task View         initialize: function(opts) {             this.model.on('change', this.render, this );         },         handle_click: function() {             if ( this.model.get('completed') ) {                 this.model.set('completed', false);             } else {                 this.model.set('completed', true);             }         }, Implementing the clicks handler Thursday, September 12, 13
  38. 38. Main App View     global.views.AppView = Backbone.View.extend({         el: $('body'),         events: {             "click .add-btn": "add_task"         },         add_task: function() {             var task_description = this.$el.find('input').val();             var tm = new global.models.Task({ text: task_description });             var tv = new global.views.TaskView({model: tm});             this.$el.find('ul').append(tv.render().el);             this.$el.find('input').val('');         }     }); Thursday, September 12, 13
  39. 39. Take Aways • Models keep data • Views show data • Views listen for model changes using on • Views listen for DOM changes using events Thursday, September 12, 13
  40. 40. Lab • Add a “Priority” field to a task • Render high priority tasks in red, medium priority tasks in yellow and normal in green Thursday, September 12, 13
  41. 41. Backbone Router • A Router connects URL with application state • This allows internal bookmarking and history management Thursday, September 12, 13
  42. 42. Hello Router • You only need one • Defines routes and handlers var router = new (Backbone.Router.extend({   routes: {     '' : 'home',     'help' : 'help'   },     home: function() {     alert('WElcome home');   },     help: function() {     alert('What can I help you with ?');   } }))();   Backbone.history.start({ pushState: true } ); Thursday, September 12, 13
  43. 43. Changing State • Use router.navigate( url ) to change state • Pass { trigger: true } if you need to also trigger the route Thursday, September 12, 13
  44. 44. Demo • Let’s add a View Task page • Shows a specific task in details • Then connect the pages using a router Thursday, September 12, 13
  45. 45. Server Side Models How to get server data using Backbone Models Thursday, September 12, 13
  46. 46. Models & The Server • Set the urlRoot property of a model to allow it to sync with your server Thursday, September 12, 13
  47. 47. Models & The Server Model Id Model Method HTTP Method Url id == 1 .fetch() GET /todos/1 id == 1 .save() PUT /todos/1 no id .fetch() GET /todos no id .save() POST /todos Thursday, September 12, 13
  48. 48. Server Events • request event is triggered when sync starts • change event is triggered when an attribute value has changed • sync event is triggered when save is completed (i.e. data is saved on server) Thursday, September 12, 13
  49. 49. Server URLs • POST /items => return a new item • GET /items/id => return an existing item by its id • PUT /items/id => change existing item by its id Thursday, September 12, 13
  50. 50. Demo: https://github.com/ynonp/mobileweb- examples/tree/master/ajax/Backbone Thursday, September 12, 13
  51. 51. Q & A Thursday, September 12, 13
  52. 52. Collections Thursday, September 12, 13
  53. 53. Collections • Groups of models • Add/Remove events • Sync from server Thursday, September 12, 13
  54. 54. Collections Feed The Zombie Plant The Brainz Do The Zombie Walk Todos Collection Todo Models Thursday, September 12, 13
  55. 55. Collection Actions • col.length : number of models in the collection • col.add(m) : add a model • col.remove(m) : remove a model Thursday, September 12, 13
  56. 56. Collection Actions • col.at( index ) : get a model at a specific index • col.get( id ) : get a model by its id Thursday, September 12, 13
  57. 57. Collection Actions • reset( array_of_models ) : sets the collection’s data Thursday, September 12, 13
  58. 58. Collections Demo • Add a Tasks collection • Add a Counter view • Show active tasks count Thursday, September 12, 13
  59. 59. Collections     global.models.TasksGroup = Backbone.Collection.extend({         model: global.models.Task     }) Define a new collection A collection needs to create objects, so we must provide the type as a class Thursday, September 12, 13
  60. 60. Collection Views • It’s ok to create a view for a collection • Just pass in the collection to the view’s new method • Render delegates its job to subviews • Demo: Create a collection view for TasksGroup Thursday, September 12, 13
  61. 61. Collection Views render: function() {   var $el = this.$el;     $el.html('');     this.collection.forEach(function(model) {     var v = new app.views.Task( { model: model } );     $el.append( v.render() );   });     return $el; }, Thursday, September 12, 13
  62. 62. Collection Views render: function() {   var $el = this.$el;     $el.html('');     this.collection.forEach(function(model) {     var v = new app.views.Task( { model: model } );     $el.append( v.render() );   });     return $el; }, Pop Quiz: What can go wrong ? Thursday, September 12, 13
  63. 63. Managing Subviews • If subviews also listen for model events, you will need to stop listening before removing the container view • Solution: keep a list of subviews in container Thursday, September 12, 13
  64. 64. More Collection Views • Same data, different views • Let’s create a counter view • Show total number of tasks Thursday, September 12, 13
  65. 65. Collections        initialize: function() {             var cv = new global.views.CounterView( { tasks: this.tasks }).render();             this.$el.append( cv.el );             this.tasks.on('add', cv.render, cv );             this.tasks.on('remove', cv.render, cv);         }, In appview.js Collections trigger events when models are added or removed Thursday, September 12, 13
  66. 66. Collections    global.views.CounterView = Backbone.View.extend({         tagName: 'div',         className: 'counter',         initialize: function(opts) {             this.tasks = opts.tasks;         },         render: function() {             console.dir(this.el);             this.$el.html( this.template( { count: this.tasks.length }));             return this;         },         template: Handlebars.compile( $('#counter-template').html() )     }); Thursday, September 12, 13
  67. 67. Lab • Modify CounterView so it will also display the number of unfinished tasks Thursday, September 12, 13
  68. 68. Other Collection Methods • forEach (function(item) { ... } ) • find • filter • include • toArray Thursday, September 12, 13
  69. 69. Collection and Server • Retrieve a collection from the server using fetch() • url is a property of collection • change event is triggered if server state is different Thursday, September 12, 13
  70. 70. Collections Server URLs • GET /items => returns all items Thursday, September 12, 13
  71. 71. Collection Events • reset event is triggered after fetch() or reset() • add() event is triggered when a model is added to a collection • remove() event is triggered when a model is removed from a collection Thursday, September 12, 13
  72. 72. Q & A Thursday, September 12, 13
  73. 73. Extending Backbone • Nested Collections • Pagination • Data Binding • Forms Thursday, September 12, 13
  74. 74. Extending Backbone • Backbone is easy to extend: • You can add functions to the Backbone namespace • You can override Backbone’s methods Thursday, September 12, 13
  75. 75. Try This • Add function toggle() to Backbone.Model to toggle bool values (true / false) Thursday, September 12, 13
  76. 76. Try This • Create a TemplateView that acts like a Backbone.View with a simple template rendering functionality built-in Thursday, September 12, 13
  77. 77. Backbone Extensions • JS Libs that extend Backbone • Really long list at: https://github.com/jashkenas/backbone/ wiki/Extensions,-Plugins,-Resources Thursday, September 12, 13
  78. 78. Nested Collections • A collection that “has” another collection • Example: Inbox and Messages Thursday, September 12, 13
  79. 79. Nested Approach Inbox Sent Drafts Models Mail Collection Thursday, September 12, 13
  80. 80. Nested Approach Inbox Sent Drafts Models msg1 msg2 msg3 Models Thursday, September 12, 13
  81. 81. Let’s Code This • Models: • Mailbox model • Message model • Collections: • Mailbox collection (for messages) • Folders collection (for mailboxes) Thursday, September 12, 13
  82. 82. This works. But... • Given a message item, can you tell in which mailbox it is ? • How do you move a message from one inbox to another ? Thursday, September 12, 13
  83. 83. Backbone-Relational • A plugin for managing relations between collections • Adds RelationalModel • http://backbonerelational.org/ Thursday, September 12, 13
  84. 84. Q & A Thursday, September 12, 13
  85. 85. Pagination • How would you implement pagination ? Thursday, September 12, 13
  86. 86. Pagination • Collection only stores partial data • Add methods to collection: • goToNextPage() • goToPreviousPage() • goToPage() Thursday, September 12, 13
  87. 87. Pagination • Need to override Backbone.sync to allow sending custom parameters to the server Thursday, September 12, 13
  88. 88. Backbone.Sync • sync(method, model, [options]) • method: create / read / update / delete • model: model or collection • options: success and error callbacks Thursday, September 12, 13
  89. 89. Backbone.Sync options • Use a global Backbone.sync to enable application wide overriding • Use a model/collection specific sync to have only that collection use your sync Thursday, September 12, 13
  90. 90. Backbone.Sync Demo • Let’s write a cacheable model that adds two methods: • cache() • invalidate() • After cache(), all read requests should return the cached copy Thursday, September 12, 13
  91. 91. Lab: Fill in the missing parts Backbone.CachedModel = Backbone.Model.extend({   cache: function() {   },     invalidate: function() {   },     sync: function(method, model, opts) {   } }); Thursday, September 12, 13
  92. 92. Take Aways • Backbone.sync allows full control on the syncing process • If you just need to add functionality, consider listening for sync events Thursday, September 12, 13
  93. 93. Pagination • Use a custom (paginated) collection • Add a sync method so it’ll send your pagination params to the server • AND Someone already did it :) Thursday, September 12, 13
  94. 94. The Backbone Way • A special collection is added using the Paginator plugin • Backbone.Paginator.requestPager Thursday, September 12, 13
  95. 95. Other Params • Paginated Collection needs: • paginator_core: an object describing how to interact with the server • paginator_ui: an object describing how to display the info • server_api: an object describing the parameters to send • Code: https://github.com/backbone- paginator/backbone.paginator Thursday, September 12, 13
  96. 96. Demo • https://github.com/backbone-paginator/ backbone.paginator/tree/master/ examples/request-paging Thursday, September 12, 13
  97. 97. Q & A Thursday, September 12, 13
  98. 98. Other Plugins • Backbone.localStorage will let you store your models locally https://github.com/jeromegn/ Backbone.localStorage Thursday, September 12, 13
  99. 99. Other Plugins • Backbone Forms will automatically create form controls for you • Also adds validation code • https://github.com/powmedia/ backbone-forms Thursday, September 12, 13
  100. 100. Other Plugins • Backbone Stickit will let you have two- ways data binding for your views • http://nytimes.github.io/backbone.stickit/ Thursday, September 12, 13
  101. 101. Extending Backbone • Extending Backbone is easy • Just create more models, views or controllers • Sometimes you’ll need to override Backbone methods Thursday, September 12, 13
  102. 102. Benefits • Lifts big apps • Scalable and very stable • No magic • Extensible Thursday, September 12, 13
  103. 103. Dark Side • Not suitable for small apps • Can be confusing for new developers • Can sometimes add clutter Thursday, September 12, 13
  104. 104. Thank You • Ynon Perek • me@ynonperek.com • ynonperek.com Thursday, September 12, 13

×