Creating Single Page Web App using Backbone JS

Post on 08-May-2015

3,670 views 0 download

description

This was presented during the workshop on the topic. The complete code of the app that was created during the workshop is available at Github https://github.com/mathurakshay/explore-venues

transcript

Creating Single Page Web Appusing

Akshay Mathur

@akshaymathu 2

Akshay Mathur

• Founding Team Member of– ShopSocially (Enabling “social” for retailers)– AirTight Neworks (Global leader of WIPS)

• 15+ years in IT industry– Currently Principal Architect at ShopSocially– Mostly worked with Startups• From Conceptualization to Stabilization• At different functions i.e. development, testing, release• With multiple technologies

What have we learnt

• Creating basic web pages– HTML tags– CSS

• Basic JavaScript and jQuery– Reading and writing DOM– Getting data using AJAX calls– Responding to browser events– jQuery templates

• CoffeeScript• Object Oriented JavaScript

– JS Classes– Extending classes using prototypes

@akshaymathu 4

BackboneJS

• Provides MVC structure for JavaScript• Built on top of UnderscoreJS• Other than Model, View and Controller

(Router) also provides Event and Collection objects– Using custom events help writing good code and

eliminates use of global variables– Array of Models with same structure can be

combined into Collection for ease of handling

@akshaymathu 5

UnderscoreJS

• Has nothing to do with MVC• Provides many useful functions on– Arrays– Objects– Array of Objects

• BackboneJS directly extends a few functions for its objects (Classes)

@akshaymathu 6

BackboneJS codeclass LoginModel extends Backbone.Modelclass LoginView extends Backbone.View

initialize: =>@template = $(’#login_template').template()@render()

render: =>$(@el).html $.tmpl(@template, @model.toJSON())

events: =>'click #login_btn' : ’login_handler’

login_handler: (ev) =>window.mpq_track ’Login Click’

class LoginController extends Backbone.Routerinitialize: =>

@l_model = new LoginModel window.app_info@l_view = new LoginView model: model, el:

’#login_div’

@akshaymathu 7

Backbone View

• A View is created by extending a Backbone’s view class

• A View always have 2 properties:– el: An HTML element that is in the root of the

View– model: Model that powers data to the View

@akshaymathu 8

Creating Viewclass LoginView extends Backbone.View

initialize: =>@template = $.template($(’#login_template’))@render()render: =>$(@el).html $.tmpl(@template,

@model.toJSON())

class LoginController extends Backbone.Routerinitialize: =>@l_model = new LoginModel window.app_info@l_view = new LoginView model: @l_model, el: ’#login_div’

@akshaymathu 9

Rendering HTML

• Typically a view has a template• In the render method, the template should be filled

with data and inserted into el– The el can be attached to DOM before or after filling HTML

class LoginView extends Backbone.Viewinitialize: =>

@template = $.template $(’#login_template’)

render: =>$(@el).html $.tmpl(@template,

@model.toJSON())

@akshaymathu 10

Browser Events

• Defining events object within a view automatically connects functions to event handlers

class LoginView extends Backbone.Viewevents:

'click #login_btn' : ’login_handler’

login_handler: (ev) =>window.mpq_track ’Login Click’

@akshaymathu 11

Design Views for

• http://explore-venues.appspot.com/

@akshaymathu 12

Thinking of Views

• Create a view for whole page– Base view that can handle anything as needed– It may be rendered by server

• A view for each unit that is logically different– Event handling is needed within

• Keep separate model for each view

@akshaymathu 13

Zombie Views

• When new views are created from a view class and attached to DOM in a way that it replaces HTML of an old view– The old view object and its events remain attached and

create issues$(“#button”).click ->

@view = new SomeView

Class SomeView extends backbone.Viewrender: =>

$(“container”).html template_html

@akshaymathu 14

Handling Zombies

• Don’t let zombies create• Use .destroy() on the View instance• Cleanup associated model if needed$(“#button”).click ->

@view = new SomeView

$(“#close_button”).click ->@view.destroy()

@akshaymathu 15

@akshaymathu 16

Backbone Model

• Model is defined extending the Backbone’s Model Class

• The Model object can be created with the data coming from the server (database)

• The data can be read later using .get() and set using .set() methods

• Transient data (not intended to be synced with server) can be stored separately

@akshaymathu 17

Creating Model

app_info = {type: 4, name: ‘Internal

Application’, protected: true

}class LoginModel extends Backbone.Model

initialize: =>@is_changed = false

class LoginRouter extends Backbone.Routerinitialize: =>

@l_model = new LoginModel app_info

@akshaymathu 18

Data Manipulation

• Readold_name = @model.get ‘name’

• Writenew_name = old_name.toLower()@model.set ‘name’, new_name@model.is_changed = true

@akshaymathu 19

Model Events

• Model object raises events on change in data– changed– remove

• These events may be captured (by view) and acted upon accordingly– A few properties are also set within the Model– Old and new values of the Model are also

available

@akshaymathu 20

Keeping UI Up-to-Dateclass LoginView extends Backbone.View

initialize: =>@model.bind(‘change’, @render)@render()

render: =>$(@el).html $.tmpl(@template,

@model.toJSON())

class LoginRouter extends Backbone.Routerinitialize: =>@l_model = new LoginModel app_info@l_view = new LoginView model:@l_model

@akshaymathu 21

Syncing with Server

• For having better control over data, one should collect data from the Model and make an AJAX call

• One can also attach a URL to the Model and RESTful AJAX calls are automatically done

@akshaymathu 22

Collections

• Simple data structure for storing many instances of same model– Array of Model objects

• Provides methods and properties for managing the list

• Can be created by extending Collection class of Backbone

@akshaymathu 23

Creating Collectionclass VenueModel extends Backbone.Model

class VenueCollection extends Backbone.Collectionmodel: VenueModel

class VenueListModel extends Backbone.Modelinitialize: =>

@e_list = new VenueCollection

class VenueListView extends Backbone.Viewinitialize: =>

@model.e_list.bind('add', @add_venue)

add_venue: (venue_model) =>

@akshaymathu 24

@akshaymathu 25

Backbone Router

• It routes URLs to respective methods• A Router is created by extending a Backbone’s

router class• Route configuration can be passed while

creating the router object instance

@akshaymathu 26

Creating Router

class LoginController extends Backbone.Routerinitialize: =>

@l_model = new LoginModel window.app_info

@l_view = new LoginView model: model, el: ’#login_div’

routes:“help”: “help”

$(document).ready ->l_router = new LoginController()

@akshaymathu 27

Route Configuration

• Rout configuration is a JavaScript object mapping URLs to functions– URL patterns may be used as key– Data can be read from URLs and passed to

functions as parameters

@akshaymathu 28

Routes at Work

routes: "help": "help” // #help "search/:query": "search",

// #search/kiwis "search/:query/p:page": "search"

// #search/kiwis/p7

help: -> search: (query, page)->

@akshaymathu 29

Catch All

• Router is sometimes used for putting methods not belonging to any other Model or View

• Router also acts as a glue for all other objects– Typically all basic views are initialized in router so

any cross-view functionality can be implemented in router

@akshaymathu 30

@akshaymathu 31

Events

• Events facilitate communication amongst different objects– Data can be passed along with events

• Browser raises events on user actions• Publish-Subscribe architecture avoids tight

coupling between objects

@akshaymathu 32

Backbone Events

• Backbone objects also raise events on various actions– add: when a model is added to a collection. – remove: when a model is removed from a collection. – reset: when the collection's entire contents have been

replaced. – change: when a model's attributes have changed. – change: when a specific attribute has been updated. – destroy: when a model is destroyed.

@akshaymathu 33

Custom Events

• Backbone’s event module can be mixed with an object– The the objects gets the ability to raise events

programmatically– The object also gets the ability to listen to the

events

@akshaymathu 34

Defining Custom Events

EventDispatcher =SHOW_VENUE: 'show_venue'CLEAN: 'clean'

_.extend(EventDispatcher,

Backbone.Events)

@akshaymathu 35

Using Custom EventsED = EventDispatcherclass VenuetView extends Backbone.View

initialize: =>ED.bind ED.CLEAN, @remove_self

class VenueListView extends Backbone.Viewinitialize: =>

@model.e_list.bind('add', @add_venue)ED.bind ED.CLEAN, @reset_col

clean_old_list: =>@venue_list_model.e_list.reset()ED.trigger ED.CLEAN

@akshaymathu 36

Go Hands-on

Explore FourSquare Venueshttp://explore-venues.appspot.com/

@akshaymathu 38

@akshaymathu 39

Design Views

• Page view– Accordion– Google Map

• Venue list view– All venue tiles

• Venue view– Single venue tile

• Venue details view (do later)– Popup with details of the venue

@akshaymathu 40

Design Models

• As a thumb rule, a model can be kept for each view– Page model– Venue list model– Venue model– Venue details model (do later)

@akshaymathu 41

Create Base HTML

• Head– Include Bootstrap CSS– Include JS

• Google Map API, jQuery’s , jQuery template• Bootstrap, Underscore, Backbone, App’s custom

• Top bar– Use navbar’s HTML from Bootstrap

• Accordion– Use Bootstrap jQuery plugin’s HTML– Create accordion headers– Keep accordion bodies blank

@akshaymathu 42

Create jQuery Templates

• No template for Google Map– Map UI is completely rendered by Google APIs

• Venue template– Each venue tile

• Venue details template (do later)– Venue details popup– Use Bootstrap modal jQuery plugin’s HTML

@akshaymathu 43

Create CoffeeScript

@akshaymathu 45

Basic Skeletonclass VenueModel extends Backbone.Modelclass VenueCollection extends Backbone.Collection

model: VenueModel

class VenueListModel extends Backbone.Modelinitialize: =>

@e_list = new VenueCollectionclass VenueListView extends Backbone.View

initialize: =>@model.e_list.bind('add', @add_venue)

class VenueView extends Backbone.View

class PageModel extends Backbone.Modelclass PageView extends Backbone.View

class VenueController extends Backbone.Router

@akshaymathu 46

Start Execution• On DOM ready event, instantiate the router

$(document).ready ->venue_controller = new VenueController

• Create an instance of page model and view in initialize routine of routerclass VenueController extends

Backbone.Routerinitialize: =>

@page_model = new PageModel@page_view = new PageView (

el: $("#maindiv"), model: @page_model)

@akshaymathu 47

Initialize Page View

• Page view initializes automatically when its instance gets created in router

• Initialize venue list

class PageView extends Backbone.Viewinitialize: =>

@venue_list_model = new VenueListModel@venue_list_view = new VenueListView(

el: $("#venue_list"), model: @venue_list_model)

@akshaymathu 48

Google Map• In page view, create Google Map object and render it in the div created for

that• Register event handler for Google Map click event

@map = new google.maps.Map($(’#map-canvas’)[0]),map_options)

google.maps.event.addListener @map, 'click', (ev) =>

@get_venues(ev.latLng.lat(), ev.latLng.lng())

@akshaymathu 49

Get Venues

• Make a JSONP AJAX call to FourSquare for getting venues near the clicked location

• Create a model from each venue in result and add to collection

venue_model = new VenueModel item.venue

@venue_list_model.e_list.add venue_model

@akshaymathu 50

Render Venue Tile

• As venue model adds into collection, the add event handler on collection is fired in venue list view

@model.e_list.bind('add', @add_venue)

• Handlers gets the venue view rendered and attaches it to the DOM

add_venue: (venue_model) =>venue_view = new VenueView(model: venue_model)tile_html = venue_view.render()$("#venue_col).append tile_html

@akshaymathu 51

Click on Venue Tile

• Venue view registers click handler by defining event mapclass VenueView extends

Backbone.Viewevents:"click" : 'show_details’

• Venue detail popup is to be shown outside base element (el) of the venue view so it raises an event

show_details: =>ED.trigger ED.SHOW_VENUE, @model

@akshaymathu 52

Showing Details Popup

• Page view listens to the event and renders details popup

class PageView extends Backbone.Viewinitialize: =>ED.bind ED.SHOW_VENUE, @show_popup

show_popup: (venue_model) =>@detail_view = new VenueDetailView model: venue_model$(@el).append @detail_view.render()

@akshaymathu 53

@akshaymathu 54

Optimization

• Venue model and Venue detail model represent exactly same entity– There is always 1-1 relation

• Same model may be used for both– First render should not be slow for bringing details

@akshaymathu 55

Thanks

@akshaymathu