Backbone React Sortable Table

By Blaine Hatab | December 21, 2014

This screencast shows you how to make a sortable table using react and backbone with a custom react mixin and backbone sorting. It uses backbone react component to interface backbone to react.

Sort Mixin

This is the sort mixin that is used on the component that contains the sortable table. You could rewrite this slightly and move this to the sortable table if that makes more sense to you.

# /javascripts/mixins/sort_mixin.js.coffee

MyApp.Mixins.SortMixin =

  getInitialState: ->
    { sortAttribute: @props.collection.sortAttribute, sortDirection: @props.collection.sortDirection }

  sortCollection: (attr)->
      newSortDirection = 1
      if @state.sortAttribute == attr
        newSortDirection = @state.sortDirection * -1

      @setState(sortAttribute: attr, sortDirection: newSortDirection)

    sortedData: ->

      sortedData = @getCollection()

      sortedData.sortDirection = @state.sortDirection
      sortedData.sortBy(@state.sortAttribute)
      sortedData

User Collection

The user collection defines which fields are displayed in the table, the initial sorting attribute, and the initial sorting direction. It uses Backbone's comparator method to sort the collection and exposes a sortBy method for resorting.

# /javascripts/collections/user_collection.js.coffee

MyApp.Collections.Users = Backbone.Collection.extend
  url: 'http://jsonplaceholder.typicode.com/users'
  model: MyApp.Models.User

  sortAttribute: 'name'
  sortDirection: 1

  sortTypes:
    'name' : 'Name'
    'website' : 'Website'

  sortBy: (attr) ->
    @sortAttribute = attr
    @sort()
    return


  comparator: (a, b) ->
    a = a.get(@sortAttribute)
    b = b.get(@sortAttribute)

    return 0 if a is b 
    if @sortDirection is 1
      (if a > b then 1 else -1)
    else
      (if a < b then 1 else -1)

Sortable Table Component

This is the sortable table component. It triggers the sortCollection method in the mixin when a th element is clicked. I use @getCollection() from backbone-react-component to get the sort attribute, sort types, and sort direction data so we don't have to pass those down as props.

# /javascripts/components/sortable_table.js.coffee

{thead, table, tbody, th, td, tr, i} = React.DOM

SortableTable = React.createFactory React.createClass
  mixins: [Backbone.React.Component.mixin]

  sortCollection: (sort_key)->
    @props.sortCollection(sort_key)

  render: ->
    table className: 'table table-bordered table-hover',
      thead {},
        _.map @getCollection().sortTypes, (sortTitle, sortKey) =>
          th onClick: @sortCollection.bind(@, sortKey), key: sortKey,
            sortTitle
            ' '
            if @getCollection().sortAttribute == sortKey
              if @getCollection().sortDirection == 1
                i className: 'fa fa-caret-down'
              else
                i className: 'fa fa-caret-up'

      tbody {},
        @getCollection().map (model)=>
          tr key: model.get('id'),
            _.map @getCollection().sortTypes, (sortTitle, sortKey) =>
              td key: sortKey, model.get(sortKey)

MyApp.Views.SortableTable = SortableTable

User Table Component

This is the table that is rendered into the page and contains the sortable table component. I use backbone's fetch method to get the data from the api url, which is defined in the user collection. Then I pass it into the component's props as collection so we can use backbone-react-component's @getCollection() method.

# /javascripts/components/user_table.js.coffee

{div, p, h1} = React.DOM

UserTable = React.createFactory React.createClass
  mixins: [
    Backbone.React.Component.mixin
    MyApp.Mixins.SortMixin
  ]

  render: ->
    div className: 'row',
      div className: 'col-xs-12',
        h1 {}, 'Backbone React Sortable Table Screencast'
        MyApp.Views.SortableTable(data: @sortedData(), sortCollection: @sortCollection)


users = new MyApp.Collections.Users

users.fetch().done ->
  React.render UserTable(collection: users), document.getElementById('home-page-wrapper')

Resources

github: https://github.com/openmindedinnovations/backbone_react_sortable_table_screencast

backbone-react-component: http://github.com/magalhas/backbone-react-component

Backbone: http://backbonejs.org/

React: http://facebook.github.io/react/

Middleman: http://middlemanapp.com/

comments powered byDisqus