Parsing forms with Backbone.js

Take a form that’s indexed in the Rails vogue.

<form id="nametagForm">
  <input type="text" name="nametag[name]" value="Barney Rubble" /><br />
  <input type="text" name="nametag[role]" value="Neighbor" /><br />
  <input type="text" name="nametag[saying]" value="Huh Huh Huh" /><br />
  <input type="text" name="nametag[family_attributes][name]" value="Betty Rubble" />
</form>

Wouldn’t it be nice to be able to manipulate its content directly through Backbone.js? With just a few additions to Backbone.View, using a model to populate a form or retrieve the form’s content becomes a trivial task:

_.extend(Backbone.View.prototype, {

  parse: function(objName) {
     var self = this,
        _recurse_form = function(object, objName) {
          _.each(object, function(v,k) {
             if (v instanceof Object) {
                object[k] = _recurse_form(v, objName + '[' + k + '_attributes]');
             } else {
                object[k] = self.$('[name="'+ objName + '[' + k + ']"]').val();
             }
          });
          return object;
        };
     this.model.attributes = _recurse_form(this.model.attributes, objName);
  },

  populate: function(objName) {
     var self = this,
        _recurse_obj = function(object, objName) {
          _.each(object, function (v,k) {
             if (v instanceof Object) {
                _recurse_obj(v, objName + '[' + k + '_attributes]');
             } else if (_.isString(v)) {
                self.$('[name="' + objName + '[' + k + ']"]').val(v);
             }
          });
        };
     _recurse_obj(this.model.attributes, objName);
  }
});

Just for the sake of demonstration, let’s get Barney out of the form and move someone else in. A really basic model and the corresponding view for Barney’s neighbor might look something like this:

var nametag = Backbone.Model.extend({
  defaults: {
     name: 'Fred Flintstone',
     role: 'Protagonist',
     saying: 'Yabba Dabba Do!',
     family: {
        name: 'Wilma Flintstone'
     }
  }
});

var nametagView = Backbone.View.extend({
  initialize: function() {
     _.bindAll(this);
  }
});

Finally, run a quick demonstration to make sure everything worked (hint: console.log(myModel.attributes);)

$(document).ready(function(){
  var myModel = new nametag();
  var myView = new nametagView({
     el: $('#nametagForm'),
     model: myModel
  });

  myView.populate('nametag');
  myView.parse('nametag');
});

Check out the demonstration here.


Update: I’ve been developing a jQuery plugin to help parse data in the DOM into javascript applications. Check it out!

Featured