Developer's Perception

Odd thoughts from a developer.

Mapping Screen Mockup to Backbone.View(s)

| Comments

One thing I have noticed after working on a Backbone powered application for 4 months is that developers have very different views on how to split a screen mockup into Backbone views in the code.

I have seen re-use of code with each and every input field being wrapped by a view and named as a control (…smells like ASP.NET web forms controls – shudders….) and potentially you could also have all the markup handled by one view.

Given a small example screen mockup for gathering simple information about a person, like this:

Lets try to look at the different ways we could implement this with Backbone views, but first let us look at the requirements:

There is a message area that greets the person when the full name has been given (should be triggered when the user leaves either field if both are filled), and similarly the message area will contain errors if something goes wrong when clicking the save button.

FirstName and SurName only allows characters (yes I am aware this excludes some people with dots in names or similarly). This should be checked when leaving the field.

Country is actually a dropdown that lists the Scandinavian countries.

With these requirements in hand we have a couple of options for implementation.

Not using Backbone at all.

Will save us the trouble of having to worry about Backbone, but since we are building this form within a Backbone powered application and it does contain several things that could benefit from Backbone this is probably not the best idea.

Using one template with all markup for this screen and one Backbone view.

This is probably a very good first implementation, with the clear benefits of having a template that is easy to read and style, but unfortunately we will also have a view that does not adhere to the Single Responsibility Principle (SRP).

Using a view with a template for every single item on the screen

This option removes all readability of the markup as it is broken into a multitude of very small fragments, and you will probably end up with a view for the entire screen with a render method like this:

1
2
3
4
5
6
7
8
render: function(){
  var firstNameInput = new control.InputView({
      model: this.model, attribute: 'heading', caption: 'FirstName', maxlength: 250
  });
  this.childViews.push(firstNameInput);
  firstNameInput.render();
  this.$('.firstNameContainer').append(firstNameInput.el);
};

Oooh… That was only for one field.

Solution

Somewhere in between all the crazy options given above the solution can be found. Maybe what we really want is a view corresponding to the screen, a view for the message area, a view for the area with the input fields, and potentially a view for the save button. It will adhere to SRP in my opinion and the markup with be in fragment sizes that are possible to mentally combine and get the overview.

It leaves us with the problem of the input area – what about the validation, binding to the model etc?

In third option this was most likely handled by the InputView.

I would suggest keeping the markup in the template, possibly enriching it with just enough information to enable binding dynamically to the model (consider using or stealing the idea of something like backbone.modelbinding). Apply the binding jQuery style at the last line in the render method (only one line) and use jQuery to find all elements requiring binding.

Thus:

  • Be careful with fragmenting the backup for a screen too much. It really reduces the overview.
  • Don’t use a view if you do not need one. A simple javascript module or function would do.
  • Leave the markup intact and decorate it for dynamically enriching it with behavior. In the ideal scenario your markup would work if javascript was disabled (albeit this does not make much sense in a Backbone application).

Your render method should be a matter of rendering a template and calling at most one method for each dynamic behavior required: modelbinding, autocomplete in some fields, or similar.

Comments