bind multiple objects in play framework 2.0 from a

2020-05-29 03:06发布

问题:

i am desperately trying to receive a list of values from a form submission and bind it to a list of objects.

What works is to retrieve a single row:

//class
case class Task(name: String, description: String)

val taskForm: Form[Task] = Form(
  mapping(
  "name" -> text,
  "description" -> text

  )(Task.apply)(Task.unapply)
)


//form
<tr>
  <td><input name="name" type="text" class="span2" placeholder="Name..."></td>
  <td><textarea name="description" class="autoexpand span7" rows="1"     placeholder="Description..."></textarea>
  </td>
</tr>

//receiving action:
val task = taskForm.bindFromRequest.get

But now i want to submit multiple objects of type task like this for instance:

<tr>
  <td><input name="name[0]" type="text" class="span2" placeholder="Name..."></td>
  <td><textarea name="description[0]" class="autoexpand span7" rows="1" placeholder="Description..."></textarea></td>                   
</tr>
<tr>
  <td><input name="name[1]" type="text" class="span2" placeholder="Name..."></td>
  <td><textarea name="description[1]" class="autoexpand span7" rows="1" placeholder="Description..."></textarea></td>                   
</tr> 

Doing a taskForm.bindFromRequest.get now fails.

Did somebody come up with a solution to this? Or do you handle such a situation totally different?

回答1:

Well, thanks for hinting me to look at the docs again, i've seen them already, but never could make up how to combine it to make it work. I think this is because i am a total scala noob. However, i got it working after giving it some time again, this is my solution:

//classes
case class Task(name: String, description: String)
case class Tasks(tasks: List[Task])

val taskForm: Form[Tasks] = Form(
  mapping(
  "tasks" -> list(mapping(
    "name" -> text,
    "description" -> text
  )(Task.apply)(Task.unapply))
)(Tasks.apply)(Tasks.unapply)
)

//form
<tr>
  <td><input name="tasks[0].name" type="text" class="span2" placeholder="Name..."></td>
  <td><textarea name="tasks[0].description" class="autoexpand span7" rows="1" placeholder="Description..."></textarea></td>                   
</tr>
<tr>
  <td><input name="tasks[1].name" type="text" class="span2" placeholder="Name..."></td>
  <td><textarea name="tasks[1].description" class="autoexpand span7" rows="1" placeholder="Description..."></textarea></td>                   
</tr>

And finally do a:

val tasks = taskForm.bindFromRequest.get

to retrieve the list of tasks.



回答2:

From the playframework documentation page:

Repeated values

A form mapping can also define repeated values:

case class User(name: String, emails: List[String])

val userForm = Form(
  mapping(
    "name" -> text,
    "emails" -> list(text)
  )(User.apply, User.unapply)
)

When you are using repeated data like this, the form values sent by the browser must be named emails[0], emails[1], emails[2], etc.