Spring MVC and Twitter Bootstrap – customizing the input fields

LOL

Creative Commons License photo credit: ~chicchun~

So, in my latest project I am using Twitter Bootstrap together with Spring MVC 3.1. It’s sort of best of both worlds as Bootstrap takes away a lot of the pain on one hand, and Spring deals with the other hand (which works well for me).
Anyway – I am not going to say much more about these guys together – just that it’s been awesome so far, and without further ado here’s a little tag I put together to allow your Spring MVC views to use the Twitter Bootstrap layout, and also display errors in the Bootstrap way.

The problem

Bootstrap has a nice way of displaying fields in error or warning state. See the screenshot below:

Error with Bootstrap

Error – the Twitter Bootstrap way

But, in Spring, because of the way the form:errors tag behaves, it is not very straightforward to get this kind of behaviour. Additionally – Bootstrap likes a lot of classes around its input fields. To solve this, and to make life easier – add this form:input wrapper tag to your arsenal:

<%@tag description="Extended input tag to allow for sophisticated errors" pageEncoding="UTF-8"%>
<%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@attribute name="path" required="true" type="java.lang.String"%>
<%@attribute name="cssClass" required="false" type="java.lang.String"%>
<%@attribute name="label" required="false" type="java.lang.String"%>
<%@attribute name="required" required="false" type="java.lang.Boolean"%>
<c:if test="${empty label}">
	<c:set var="label" value="${fn:toUpperCase(fn:substring(path, 0, 1))}${fn:toLowerCase(fn:substring(path, 1,fn:length(path)))}" />
</c:if>
<spring:bind path="${path}">
	<div class="control-group ${status.error ? 'error' : '' }">
		<label class="control-label" for="${path}">${label}<c:if test="${required}"><span class="required">*</span></c:if></label>
		<div class="controls">
			<form:input path="${path}" cssClass="${empty cssClass ? 'input-xlarge' : cssClass}"/>
			<c:if test="${status.error}">
				<span class="help-inline">${status.errorMessage}</span>
			</c:if>
		</div>
	</div>
</spring:bind>

Explain?

  • Line 6 – The path attribute links to the Model‘s attribute for this form (the model is defined on the form:form tag) – this is the only mandatory attribute.
  • Line 7 – The cssClass is sent directly to the input tag (through the form:input> in line 17). It is optional, and defaults to Bootstrap’s input-xlarge class.
  • Line 8 – The label attribute is used in the control-label (so that’s the caption of the input field). It is optional, and defaults to the path value with the first letter capitalized.
  • Line 9 – The required attribute is used to signal that this field is required (and will have a little asterisk). Again, this is an optional attribute, and defaults to false.
  • Lines 10-11 – Test whether the label attribute is empty. If it is – the code sets the label attribute to the value in the mandatory path attribute, but capitalizes the first letter.
  • Line 12 – bind to the path attribute of the model. This is important to handle errors correctly.
  • Line 13 – Bootstrap likes to have each form-control surrounded by a div element with the control-group class. Inside the class attribute, the tag tests whether there’s an error on this path. (The status is bound using spring:bind in line 12). If there’s an error – the error class is added to the div.
  • Line 14 – The control label for the input field. Note the test (The <c:if part) that adds the red asterisk if the field is marked as required.
  • Line 16 – Delegate to Spring’s form:input tag to create and bind the input element. Note the default css class added if the cssClass attribute is empty.
  • Line 17-19 – If the bound status contains an error, the tag adds the error span. (Note that this is specific to the case where you want the error message to appear to the right
    of the field).

In your JSP page, you can use the new tag like so (I assume the tag is located in a file named input.tag under WEB-IBF/tags) :

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>
.
.
<form:form method="post" class="form-horizontal" modelAttribute="person">
   <fieldset>
      <t:input path="firstNames" label="First Name(s)"/>
      <t:input path="surname" required="true"/>
      .
      .
</form:form>

Hope this helps, good luck!

7 thoughts on “Spring MVC and Twitter Bootstrap – customizing the input fields

  1. Matt Martin

    Looks useful! Under what terms can the tag code be reused? Is it free for commercial use?

  2. Peter Drinnan

    I’ve read from some people that you can use a Bootstrap theme for PrimeFaces. Still, I am really happy with Bootstrap and since so many people are now working with it, it seems likely worthwhile to work the bugs out in terms of using it with Spring. Anyone have a strong opinion on this?

  3. Pingback: Chase Woodford | on being a designer/developer: reason #1

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>