Cark
Cark

Reputation: 31

How do you post a form field collection to a Spring controller?

Suppose I have form such as this:

<form method="post" action="/create">

    <input type="text" name="title.0" value="Curious George" />
    <input type="text" name="author.0" value="H.A. Rey" />
    <input type="text" name="date.0" value="2/23/1973" />

    <input type="text" name="title.1" value="Code Complete" />
    <input type="text" name="author.1" value="Steve McConnell" />
    <input type="text" name="date.1" value="6/9/2004" />

    <input type="text" name="title.2" value="The Two Towers" />
    <input type="text" name="author.2" value="JRR Tolkien" />
    <input type="text" name="date.2" value="6/1/2005" />

    <input type="submit" />
</form>

How do I parse this from a Spring MVC 3.0 controller?

Upvotes: 3

Views: 6211

Answers (3)

kieron
kieron

Reputation: 91

If you can change the view, ideally you'd do this with some kind of list.

Something like:

<input type="text" name="books[0].title" value="Curious George" />
<input type="text" name="books[0].author" value="H.A. Rey" />
<input type="text" name="books[0].date" value="2/23/1973" />

you would have a Book class containing your 3 elements. and a containing class which contains a list of books BookContainer

public class BookContainer {
  private List <Book> books = new ArrayList<Book>();

  public List<Book> getBooks() {
    return books;
  }

  public void setBooks(List<Book> books) {
    this.books = books;
  }
}

Now in your controller, you'd have a @ModelAttribute method which returns the Containing class to to bind to:

@ModelAttribute("container")
public BookContainer getBookContainer() {
  return new BookContainer;
}

finally you'd have a @ModelAttribute parameter to your request mapping method:

@RequestMapping
public void handlePost(@ModelAttribute("container") BookContainer container) {

}

spring will automatically add as many 'Book's to your list as you need.

Upvotes: 4

Bozho
Bozho

Reputation: 597164

The name attribute need not be unique. So:

<input type="text" name="title" value="Curious George" />
<input type="text" name="title" value="Code Complete" />
<input type="text" name="title" value="The Two Towers" />

And then

@RequestMapping("/create")
public void create(
    @RequestParam("title") List<String> titles, 
    @RequestParam("author") List<String> authors, ..) {..}

The order of the elements should be preserved, according to the spec:

The control names/values are listed in the order they appear in the document. The name is separated from the value by '=' and name/value pairs are separated from each other by '&'.

Upvotes: 9

digitaljoel
digitaljoel

Reputation: 26574

Could your controller request mapping simply take a spring WebRequest as the parameter and then do something like:

Map<String, String[]> params = request.getParameterMap();
int i = 0;
while ( true ) {
    String title = params.get( "title" + .i );
    if ( title != null ) {
        // get the rest and create your Book object or whatever
        i += 1;
    }
    else {
        break;
    }
}    

Upvotes: 1

Related Questions