12 October 2012

Easier Backbone form views with Backtastic

Over the last couple of years, we at Gaslight have built a lot of web applications that consist of a Backbone.js front end talking to a rails backend.

Backbone.js is lightweight and relatively un-opinionated, and this is a large reason it’s been so successful. But this also means that there is still a fair bit of manual work to do on the backbone.js side. Particularly if you’re building a form-heavy app and are used to rails, some of this work can feel quite tedious. In no particular order, some of the non-trivial bits that are left to you:

  • building form markup
  • moving data back and forth from your views to your models
  • dealing with errors from the backend and rendering appropriate error messages
  • validation (client-side or server-side)

Backtastic is a framework I started to try and extract some of the code I found myself needing on several projects and automate away as much as I could of this effort. The easiest way to explain what it’s about is by example. Let’s say you have a person view within your Backbone.js app that persists to a Person model in rails:

Edit Person

With Backtastic, here’s what the Backbone view code would look like:

class Example.Views.EditPersonView extends Backtastic.Views.FormView
  template: JST["edit_person_view_template"]

  constructor: (options)->
    super
    @occupations = options.occupations

  events:
    "submit form": "save"

  render: ->
    super
    @$el.addClass "modal"

  edit: (person)->
    @model = person
    @render()
    @$el.modal "show"

  close: ->
    @$el.modal "hide"

The first thing you’ll notice is that there’s nothing in this code to deal with the form, either rendering it or populating it’s values onto the model. That’s because backtastic takes care of this for us: we get this functionality because our view extends from Backtastic.FormView. Notice also the form submit event is bound to save. This method is inherited from Backtastic.View, and as you might guess, calls save on the model after it has been populated with it’s values from the form.

Now let’s look at the view template:

.modal-header
  %a{class: "close", href: "#people/list"} x
  %h3 New Person
%form.person-form
  .modal-body
    %fieldset
      = @textField(field: "first_name", label: "First Name")
      = @textField(field: "last_name", label: "Last Name")
      = @checkBoxField(field: "evil", label: "Evil")
      = @dateField(field: "birth_date", label: "Birth Date", format: "yyyy-mm-dd")
      = @selectField(field: "occupation_id", label: "Occupation", collection: @occupations)
  .modal-footer
    %input{type: "submit", value: "Save", class: "btn btn-primary"}

Here we see the view helper methods that build form elements. Again, we get these methods from Backtastic.FormView. They do more than just render form element markup, though. What they’re actually doing is creating subviews, or smaller views that render within our larger form view. Each view is responsible for:

  • rendering form element markup
  • listening to form element events and updating the model
  • listening for validation errors from the model and displaying them

There are form element subviews and corresponding helper methods for text fields, checkboxes, select boxes, and date pickers. Expect more to come along soon, and pull requests are of course welcome.

The observant reader might also notice that we’re using Twitter Bootstrap. This gives us nice layout for our forms, and gives us some help with displaying validation errors as well.

Validation in Backtastic

Backbone, out of the box, doesn’t really give us much help in the way of validation. We have a validate method on Backbone.Model, and are left to implement it ourself. Returning anything non-null from this method indicates failure, but it’s up to us what exactly it returns and what it means.

Backtastic gives us a bit more help, particularly if you are using rails at the back end. First, if you respond with validation errors from rails as json, Backtastic will decode this JSON and send it to any response handlers that are listening to “error” events on your Backbone models. And conveniently, all the form field subviews register themselves as listeners to their model’s error event and will display errors for their own field. We leverage twitter bootstrap’s css to provide nice styling for error messages.

But what about doing validation on the client side? It’s worth pointing out that client side validation by itself is never good enough. Because you always need validation on the server side, Backtastic gives you a way to easily bring the validations from your rails models to your backbone models.

Here’s how it works: Backtastic ships with a rake task, backtastic:validations:build, which will reflect on all ActiveRecord models and generate a file representing their validations in a format backtastic can understand. Here’s what this looks like in the example app:

Backtastic.Rails =
  validations: {}

Backtastic.Rails.validations.Occupation = {}

Backtastic.Rails.validations.Person = {"first_name":{"presence":{}},"last_name":{"format":{"with":"/^J.*/"}}}

Somewhere in the setup of your client side app, you can then pass this validation data to backtastic by calling Backtastic.applyValidations. Here’s what this looks like:

#= require_self
#= require_tree ./templates
#= require_tree ./models
#= require_tree ./views
#= require_tree ./routers
#= require rails_validations

window.Example =
  Models: {}
  Collections: {}
  Routers: {}
  Views: {}

$ ->
  new Example.Routers.PeopleRouter()
  Backbone.history.start()
  Backtastic.applyValidations(Example.Models, Backtastic.Rails.validations)

The first arg is the namespace in which to find backbone model classes and the second arg is the validation data. The net effect is that we now have validations executing on the client side when I make changes to a field. Right now, this works for a subset of validations: presence and format so far. Expect this list to grow as Backtastic matures.

See for yourself

The best way to dig in to Backtastic further is to poke around the example app. All the code in this post come straight from this app, which you can get to by cloning backtastic on the GitHub and running the rails app in the example directory.

Backtastic needs you!

It’s still early times for Backtastic, and it’s a great time to jump in. We’d love to see people contribute more types of form field views and additional validations, just to throw out a couple ideas. These both should be pretty easy to jump in with by following the “monkey see, monkey do” approach from the form fields and validations that already there.

Heads up! This article may make reference to the Gaslight team—that's still us! We go by Launch Scout now, this article was just written before we re-introduced ourselves. Find out more here.

Related Posts

Want to learn more about the work we do?

Explore our work

Ready to start your software journey with us?

Contact Us