• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Vanjs backbone-powerpoint

Vanjs backbone-powerpoint






Total Views
Views on SlideShare
Embed Views



1 Embed 5

https://twitter.com 5



Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
Post Comment
Edit your comment
  • * mention backbone videos
  • * Read the Code
  • busienss logic not handled on the client side
  • * This is how backbone is good for multipage application * Great if you concatenate your javascript into one file and run on all your pages * Helps prevent unexpected behavior when adding functionality to the same area of your application
  • * based on rails file structure * vendor contains 3rd party libraries * views, models, collections and templates contain their respective backbone object types * lib - libraries you write to help you throughout your application * application.js - simple manifest file, describes build order
  • - main.js is the entry point of our application - defines a namespace we will use in all our other files to call our code
  • * make sure to use a script tag and not just any dom element * otherwise, may generate invalid markup which will result in bugs * we grab content from template in script tags using the ID and add it to the dom
  • remind them about what our application does
  • * initialize a collection
  • Remember to talk about the potential for memory leaks (and unwanted behavior) Go over slide with craig
  • * Have not used before, but look at it * Flexible and can use only the pieces you need * If nothing else it provides us with formal language to talk about concepts * View Management is biggest take away * Layout -> contains regions -> views * Regions manage screen real-estate, views just know how to render themselves but nothing about where they are rendered. * Prevent zombie views * Adds the concepts of controllers

Vanjs backbone-powerpoint Vanjs backbone-powerpoint Presentation Transcript

  • Backbone in Multipage Apps Michael Yagudaev @yagudaev michael@0idle.com July 2013
  • Outline  About Me  Why Backbone?  Pain Points with Backbone  Design Patterns/Best Practices  Marionette.js
  • About Me (@yagudaev)  Co-founder of 0idle.com – an online marketplace for event organizers to find the perfect venue.  Built 0idle using Rails + Backbone.js  Entrepreneur and Rails Developer  Worked with Node.js  Started Winnipeg.js User Group  Consulting/Freelance work
  • Why Backbone.js?  Simple  Flexible – use only the parts you need  Easy to integrate into existing code  Provides structure to your app  Proven  Well Documented (for the most part )  Good for hybrid apps
  • 5 A Pain in the Back...  Due to its un-opinionated approach, backbone can be a real pain in the a**.  No clear guidelines  Lots of boilerplate code  Does not provide helpers to solve common problems  Easy to get memory leaks by not being careful when using events (zombie views)
  • Underline Principle for this talk  In any web system, the server should have the final say  Therefore, lets start developing server-side code first  Server-side code is easier to test (simple request/response)  Client-side functionality is to be considered as an added bonus in agile software development  You can do without backbone when you first start a project (KISS)  Assumption: a team of one
  • 7 Design Patterns Lets start simple and work our way up...
  • Scoping Your Selectors  Problem: Overly generic jQuery selectors can cause unexpected behavior when adding a new feature to a particular area of an application.  Example: $(‘.btn-add’).click(addNewReply); // Will conflict with: $(‘.btn-add’).click(addNewMessage);  Solution: Use a backbone View
  • var MessageView = Backbone.View.exend({ el: $('#messages-page'), events: { 'click .btn-add': 'addMessage' }, addMessage: function(ev) { $target = $(ev.currentTarget) // code to add message } }); var RepliesView = Backbone.View.exend({ el: $('#replies-page'), events: { 'click .btn-add': 'addReply' }, addMessage: function(ev) { $target = $(ev.currentTarget) // code to add message } }); $(function() { repliesView = new RepliesView(); messagesView = new MessagesView(); });
  • File Structure  Problem: Your one javascript file becomes long and hard to maintain. You need a better way to separate concerns.  Solution: Break down project into folders based on object types in backbone with a main.js file that acts as the entry point of the application and defines a namespace.  Notes: you will need to use a make or a make like solution to stitch the files together (e.g. Rails asset pipeline or h5bp build tool).  Note 2: Keep it simple. Avoid using an AMD loader like RequireJS at this stage.
  • |____application.js -- manifest file (can have more than one) |____collections/ |____lib/ |____main.js |____models/ |____templates/ |____views/ | |____messages_view.js | |____replies_view.js |____vendor/ | |____backbone.js | |____jquery.js | |____underscore.js File Structure (folders)
  • File Structure (manifest) In Rails: //= require jquery //= require underscore //= require backbone //= require main //= require_directory ./models //= require_directory ./lib //= require_directory ./collections //= require_directory ./views
  • File Structure (files) window.APP_NAME = { Models: {}, Collections: {}, Views: {}, Lib: {} }; main.js - views/messages_view.js - APP_NAME.Views.MessagesView = Backbone.View.extend({ ... });
  • Template
  • Templates  Problem: You need to dynamically generate html content, but do not want pollute your js code with html markup.  Example: a dynamic file uploader allowing the user to upload any number of files.  Solution: place your html inside a script tag and use jQuery to extract the content of the template and then render it to the page. Alternatively you can use JST to give each template a separate file.
  • 16 Templates <script id="photo-thumbnail-template" type="text/template"> <div class="thumbnail"> <img src="{{image_url}}" /> {{title}} </div> </script> $thumbnail = $(Mustache.to_html($("#photo-thumbnail- template").html(), photo)) $thumbnail.appendTo('.photos-preview.thumbnails')
  • 17 Template Sharing
  • Template Sharing  Problem: You have a template you want rendered both on the client and server.  Example: you have a photo uploader that lets the user upload multiple photos and see photos that were already uploaded.  Solution: refactor the template into a mustache template and provide access to it from both the client and the server.  Limitation: cannot use helper methods (unless you are using Node.js)
  • 19 Template Sharing //.. <%- @photos.each do |photo| -> <%= render 'photo_item', mustache: photo %> <%- end %> //.. <script type="text/template" id="photo-item-template"> <%= render 'photo_item' %> </script>
  • Client-side View Injection
  • Client-side View Injection  Problem: Similar to Template Sharing, but you are interested in re-using server-side helpers and do not care about filling in information in the template.  Example: a survey application which displays existing questions and allows to dynamically add new questions.  Solution: pre-render a partial somewhere in the DOM and to make it accessible to the client side code.
  • 22 Client-side View Injection // ... addSpace: function() { var html = this.$('.btnAdd').data('view'); $('body').append(html); } // ... <a href="#" class="btnAdd" data-view="<%= render 'space_card' %>"> Add Space </a>
  • View Helpers  Problem: You want to change the format in which your information is displayed in the view, but the logic will be too complicated to be added directly in the view.  Example: Format a date.  Solution: Define a view helper to handle this functionality.
  • 24 // app/javascripts/helpers/application_helper.js function formatDate(date) { moment(date).format("MMM Do YY"); } // if using handlebars Handlebars.registerHelper("formatDate", formatDate); // Usage (in the templates): {{formatDate date}}
  • Bootstrap Data  Problem: You need to share data between the client- side code and the server code. At the same time you would like to avoid incurring the cost of another HTTP request.  Example: You want to check if a user is logged in before you allow them to IM other users.  Solution: Use server-side processing to initialize your model(s).
  • 26 <script> (function() { var user; // preprocessed file to bootstrap variables from ruby to javascript window.ZI = { Config: {}, Models: {}, Collections: {}, Views: {}, Lib: {}, currentUser: function() { var user_data = <%=raw current_user ? current_user.to_json : 'null' %>; if (user_data) return user = user || new ZI.Models.User(user_data); return null; } }; // ... after the model has been loaded ... console.log(ZI.currentUser() === null); // not logged in console.log(ZI.currentUser() !== null); // logged in })(); </script>
  • 27 Bootstrap Data (e.g. 2) var photos = new Backbone.Collection; photos.reset(<%= @photos.to_json %>);
  • Mixin  Problem: You have code that is common between several views or models, but it does not make sense to move code into a parent class.  Example: Code that allows you to open a message dialog and can be opened from several different views.  Solution: Use a mixin to include the common code in the target views or models.
  • 29 ZI.Mixins.Navigation = { openMessageDialog: function(ev) { ev.preventDefault(); return $('#message-modal').modal(); } }; App.Views.VenuesView = Backbone.View.extend( _.extend({}, App.Mixins.Navigation, { //.. })); App.Views.MessagesView = Backbone.View.extend( _.extend({}, App.Mixins.Navigation, { //... }));
  • 30
  • Parent-Child (Sub Views) Views  Problem: You have a view that needs to communicate with another view and can be thought of as logically containing that view.  Example: Updating a dropdown after a user creates a new item through a modal dialog.  Solution: Create a reference to the child view from the parent view and listen on events fired by the child view.
  • 32 ZI.Views.NewVenueModalView = Backbone.View.extend({ el: $('#new-venue-modal'), events: { 'click .btn-primary': 'save' }, initialize: function() { return this.formView = new ZI.Views.VenueFormView(); }, save: function() { var _this = this; return this.formView.save({ success: function() { _this.trigger('save', _this.formView.model); return _this.close(); }, error: function() { return _this.trigger('error', arguments); } }); }, open: function() { return this.$el.modal(); }, close: function() { return this.$el.modal('hide'); } }); // singleton pattern ZI.Views.NewVenueModalView.getInstance = function() { return this.instance != null ? this.instance : this.instance = new this; }; Child View
  • 33 Parent View var openNewVenueDialog = function(e, data) { var new_venue_modal_view = ZI.Views.NewVenueModalView.getInstance(); new_venue_modal_view.on('save', function(model) { $('#space_venue_id').append("<option>" + (model.get('name')) + "</ option>"); $('#space_venue_id').val(model.get('id')); }); new_venue_modal_view.open(); };
  • 34 Two-Way Binding
  • Two-Way Bindings  Problem: You need to dynamically and automatically update a UI element when the underling data changes.  Example: Recalculate and display the total amount in a shopping cart if the quantity of any of the items changes.  Solution: Use a two-way binding plugin for backbone called backbone.stickit.
  • 36 ZI.Views.EventDetailsBookView = Backbone.View.extend({ el: $('#event-details-booking-page'), model: new Booking(), bindings: { '.total-price': { observe: ['start_date', 'start_time', 'end_date', 'end_time'], onGet: function(values) { return '$' + this.calculateHoursBooked(values) * this.hourly_price; } }, '#booking_start_date': 'start_date', '#booking_end_date': 'end_date', '#booking_start_time': 'start_time', '#booking_end_time': 'end_time' }, initialize: function() { this.hourly_price = this.$el.data('hourly-price'); return this.stickit(); }, calculateHoursBooked: function(values) { //... } });
  • Marionette.js  Provides architectural infrastructure for backbone.  View Management  Layouts  Regions  Specialized View Types  Memory management  Messaging  Application - controllers, modules, etc
  • References  Railscasts - http://railscasts.com/episodes/196-nested-model-form-revised  Backbone Patterns: http://ricostacruz.com/backbone-patterns/  Backbone.js - http://backbonejs.org/  Marionette - http://marionettejs.com/  Backbone.Stickit - http://nytimes.github.io/backbone.stickit/
  • 40 References  Handlebars - http://handlebarsjs.com/  Mustache - http://mustache.github.io/