Vanjs backbone-powerpoint

  • 867 views
Uploaded on

 

More in: Technology , Business
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
867
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
9
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • * 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

Transcript

  • 1. Backbone in Multipage Apps Michael Yagudaev @yagudaev michael@0idle.com July 2013
  • 2. Outline  About Me  Why Backbone?  Pain Points with Backbone  Design Patterns/Best Practices  Marionette.js
  • 3. 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
  • 4. 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. 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)
  • 6. 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. 7 Design Patterns Lets start simple and work our way up...
  • 8. 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
  • 9. 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(); });
  • 10. 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.
  • 11. |____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)
  • 12. 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
  • 13. File Structure (files) window.APP_NAME = { Models: {}, Collections: {}, Views: {}, Lib: {} }; main.js - views/messages_view.js - APP_NAME.Views.MessagesView = Backbone.View.extend({ ... });
  • 14. Template
  • 15. 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. 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. 17 Template Sharing
  • 18. 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. 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>
  • 20. Client-side View Injection
  • 21. 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. 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>
  • 23. 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. 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}}
  • 25. 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. 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. 27 Bootstrap Data (e.g. 2) var photos = new Backbone.Collection; photos.reset(<%= @photos.to_json %>);
  • 28. 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. 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. 30
  • 31. 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. 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. 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. 34 Two-Way Binding
  • 35. 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. 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) { //... } });
  • 37. Marionette.js  Provides architectural infrastructure for backbone.  View Management  Layouts  Regions  Specialized View Types  Memory management  Messaging  Application - controllers, modules, etc
  • 38. 38 QUESTIONS
  • 39. 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. 40 References  Handlebars - http://handlebarsjs.com/  Mustache - http://mustache.github.io/