我有一个重复值的表单:
val editPropertiesForm = Form(
single(
"prop" -> seq(
tuple(
"color_id" -> longNumber,
"size_id" -> longNumber,
"quantity" -> longNumber
)
)
)
)
下一步该怎么做?如何渲染表:
size1 size2 ... sizeN
color1 q1_1 q1_2 ... q1_N
color2 q2_1 q2_2 ... q2_N
... ... ... ... ...
colorM qM_1 qM_2 ... qM_N
我无法理解如何对表单的值进行分组并渲染它们。
答案 0 :(得分:0)
首先创建一个动作,根据需要填充表单数据并将其传递给视图。
def showForm = Action { implicit request =>
val sampleData = Seq((11L, 12L, 13L), (21L, 22L, 23L))
val form = editPropertiesForm.fill(sampleData)
Ok(views.html.form(form))
}
视图可以使用帮助器 repeat()方法迭代表单seq。
@(propForm: Form[Seq[(Long, Long, Long)]])(implicit request: RequestHeader)
@import helper._
<form action="@routes.FormController.handleForm()" method="post">
@helper.repeat(propForm("prop")) { row =>
<input id="@row("color_id").id" name="@row("color_id").name" value="@row("color_id").value">
<input id="@row("size_id").id" name="@row("size_id").name" value="@row("size_id").value">
<input id="@row("quantity").id" name="@row("quantity").name" value="@row("quantity").value">
<br>
}
<input type="submit" value="Send">
</form>
您应该考虑使用custom field constructors来保持视图清洁。
最后在第二个动作中处理表单。
def handleForm = Action { implicit request =>
editPropertiesForm.bindFromRequest.fold(
formWithErrors => BadRequest(views.html.form(formWithErrors)),
prop => {
prop.foreach { row =>
val colorId = row._1
val sizeId = row._2
val quantity = row._3
}
Ok(prop.toString())
}
)
}
使用普通的case类替换表单元组也可以提高代码的可读性。
答案 1 :(得分:0)
我使用rowHeader和columnHeader列表,其中包含渲染头的名称和ID。
表格
val editOrderForm = Form(
single(
"order" -> list(
tuple(
"size_id" -> longNumber,
"color_id" -> longNumber,
"quantity" -> optional(longNumber)
)
)
)
)
转换表格的助手
@tableModel(formForTableModel: Form[scala.List[(Long, Long, Option[Long])]]) = @{
formForTableModel("order").indexes
.map { ind =>
val fieldNamePrefix = s"order[$ind]"
val a = (formForTableModel(fieldNamePrefix + ".size_id").value, formForTableModel(fieldNamePrefix + ".color_id").value) match {
case (Some(sizeId), Some(colorId)) =>
Some((sizeId.toLong, colorId.toLong))
case _ =>
None
}
a.map(p=> (p._1, p._2, formForTableModel(fieldNamePrefix)))
}
.filter(f=> f.isDefined)
.flatten
}
简单助手输入HTML输入
@constr1(elements: FieldElements) = {
@elements.input
}
使用二维数据渲染表
<form action="@routes.xxx" method="post" data-product-id="@productId">
@defining(tableModel(orderForm)) {model =>
<table class="order-table table table-bordered table-condensed table-responsive">
<tr>
<td></td>
@columnHeaders.map{columnHeader =>
<td>@columnHeader._2</td>
}
</tr>
@rowHeaders.map{rowHeader =>
<tr>
<td>@rowHeader._2</td>
@columnHeaders.map{columnHeader =>
@model.find(f => f._1==columnHeader._1 && f._2==rowHeader._1).map(_._3).fold{
<td class="order-cell blocked"></td>
}{field =>
<td class="order-cell @state(field("quantity"))">
@inputText(field("size_id"), 'type -> "hidden")(FieldConstructor(constr1), lang)
@inputText(field("color_id"), 'type -> "hidden")(FieldConstructor(constr1), lang)
@inputText(field("quantity"), 'type -> "number", 'autocomplete -> "off", 'min -> "0", 'maxlength -> "3", 'size->"3")(FieldConstructor(constr1), lang)
</td>
}
}
</tr>
}
</table>
}
<div class="actions">
<input type="submit" value="Save" class="btn btn-primary">
<a class="btn btn-default cancel" href="@routes.ReservationController.showReservation(reservationId)">Cancel</a>
</div>
</form>