Multiple Spring MVC forms on a page and dynamic checkboxes

Here are some lessons learned with working with the form:checkboxes tag in Spring MVC.

First, the use case: We’ve got a list of objects (we’ll call them “keywords”). We show them in a list on the page. You can click the “Edit” link next to each one, and edit the keyword name right inline in the list, and click save, whereupon an ajax call sends the edits to be persisted. Because of the inline edit feature, each row in the list is basically a form; you can thus have n forms on a page. Furthermore, each keyword item has a list of checkboxes that are dynamically read from the database. Think of them as categories–a keyword can have many categories, and a category can have many keywords.We were able to set up these checkboxes for each keyword with basically one line of code in the .jsp file–basically one tag. Here’s what the page looked like:

    <li>
        <form:form modelAttribute="keywordForm${k.id}" name="form_${k.id}" id="form_${k.id}" action="${pageContext['request'].contextPath}/admin/editKeyword/${k.id}">
            <form:input path="keyword" type="text" value="${k.keyword}"/>
                <form:checkboxes path="selectedCategoryIds" items="${categoryList}" itemValue="id" itemLabel="name"/>
            <form />
            <form>
        </form>
    </li>

A couple of things about this code. First, notice the items attribute on the form:checkboxes tag. This is a list of items put on the page that represents all of the possible checkboxes to be checked. Second, notice the path attribute on the tag. This corresponds to a list on the form object. This form object is the model attribute for each form (more on this form model attribute shortly). Basically, if the item from the items list is present in this form’s list (corresponds to a selectedCategoryIds field, along with appropriate getters and setters), this item will appear checked. This also means that checked items will be part of this selectedCategoryIds list when the particular form is posted to the server. Remember, although there are possibly multiple forms on the page, only one form will be posted at a time. Finally, notice the modelAttribute in the form:form tag. We’re appending the id of each keyword found in the foreach. The reason this is done is that each of the n forms on the page can have its own unique attribute. In the corresponding controller method that creates this data, here’s the relevant code from the controller showing how this is done:

for(Keyword k : keywords) {
      KeywordForm f = new KeywordForm();
      f.setId(k.getId());
      f.setKeyword(k.getKeyword());
      f.setSelectedCategoryIds(new ArrayList());
      for(Category c : k.getCategories()) {
          f.addSelectedCategoryId(c.getId());
          for(KeywordForm kf : keywordForms) {
                model.addAttribute("keywordForm" + kf.getId(), kf);
          }
    }
}

First, for each keyword we have, we create a new keywordForm. We set the id and keyword fields, and then grab all the ids from a keyword’s category objects to create a list of ids, to keep the form lightweight. We then add the new keywordForm to the model, creating a unique key for it by appending the id to the string “keywordForm”. This is what is referred to in the modelAttribute form attribute on the page. This magic can happen because we are foreach-ing on the keywords that are also added to the model to be sent to the page (in code not shown here). This allows us to set the path attribute on the form:checkboxes tag so that it is bound correctly to the list on the form object. We have to do all this because we’re in a foreach loop. We have a var element, but we can’t refer to it in modelAttribute, and therefore can’t use it in path. Additionally, if we just threw a keywordForm object on the model, without uniqueness, any time we have more than one form on the page, Spring wouldn’t know which one to use/bind to.

Advertisements

About buffalobillion

Web Developer, JavaScript Balrog, Java dude, Ruby/Rails enthusiast. Guitar Playa.
This entry was posted in Web Dev. Bookmark the permalink.

2 Responses to Multiple Spring MVC forms on a page and dynamic checkboxes

  1. Chuck S says:

    Great article! Really nice to see an advanced treatment of form:form and modelAttribute after so many newbie articles all over the web. Keep up the good work!

  2. Thanks! Glad it helped.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s