Play with Scala 中的复选框列表
Checkbox lists in Play with Scala
我有...
- a
Seq[RoleId]
定义用户可以获得的所有角色
- a
User
with a 属性 roles: Seq[RoleId]
,其中角色是用户已被授予的角色
- 一个 Play 控制器准备一个表单并将用户(包括她的角色)和可用 RoleId 的 Seq 作为表单数据的一部分(包括映射)提供给 html 页面
- 一个显示每个可用角色复选框的 Twirl 模板
我想要实现的是一个复选框列表,其中每个值属于用户角色的复选框都被选中。因此该列表应该显示哪些可用角色被授予用户,如这个非常精致的原型所示:
Name: [Doe, John]
Roles: [ ] Admin
[x] Manager
[x] Service Desk
[ ] Jack of all trades
如果用户名为 John Doe
,角色为 Manager
和 Service Desk
。
这看起来很简单,但我无法找到一种方法来实现它而不需要一些技巧(比如绕过表单并将角色日期作为常规参数移动到 Twirl 模板;在表单中编写自定义映射器处理代码等)。没有所有样板文件,有没有办法以 Play 方式做到这一点?
我用谷歌搜索,但找不到任何似乎正确的例子。 Play 的表单处理文档也没有帮助。
有什么想法吗?
在完善我的问题后,我想出了一个有效的解决方案。
我使用下面的形式,它使用下面的案例 类 来保存它的数据。如您所见,内部有一个嵌套映射,表示角色列表及其与用户角色相关的状态(true 表示用户拥有该角色,否则为 false):
def userForm(implicit messages: Messages): Form[UserFormData] = Form(
mapping(
"firstName" -> nonEmptyText(minLength = 2, maxLength = 30),
"lastName" -> nonEmptyText(minLength = 2, maxLength = 40),
"email" -> email,
"roleAssignments" -> seq(
mapping(
"roleIdStr" -> nonEmptyText,
"isAssigned" -> boolean
)(RoleAssignment.apply)(RoleAssignment.unapply)
)
)(UserFormData.apply)(UserFormData.unapply)
)
case class UserFormData(firstName: String, lastName: String, email: String, roleAssignments: Seq[RoleAssignment])
case class RoleAssignment(roleIdStr: String, isAssigned: Boolean)
控制器只是用数据库中的数据填充表单:
def user(id: Long) = Action.async { implicit request =>
managerService.retrieveByIdWithRoles(id, Some(request.identity), request.remoteAddress).map { case (user, roles) =>
Ok(views.html.admin.administration.show_user(
userForm.fill(UserFormData(user.firstName, user.lastName, user.email, roleAssignments(roles)))))
}
}
private def roleAssignments(roles: Seq[Role]) = {
val roleIds = roles.map(_.id)
Roles.all.map { case id =>
RoleAssignment(id.toString, roleIds.contains(id))
}
}
并且在视图模板中我重复了 roleAssignments 并使用 repeatWithIndex
提供的索引来访问 seq 的元素:
@repeatWithIndex(userForm("roleAssignments")) { (roleAssignment, index) =>
@b4.checkbox(userForm(s"roleAssignments[$index].isAssigned"), '_text -> userForm(s"roleAssignments[$index].roleIdStr").value, '_custom -> true, 'readonly -> true)
}
谢谢@cchantep 鼓励我更加努力。
Play 库提供了一个 inputCheckboxGroup,其工作方式与 inputRadioGroup 相同。
在您的 Play 控制器中:
def userForm(implicit messages: Messages): Form[UserFormData] = Form(
mapping(
"firstName" -> nonEmptyText(minLength = 2, maxLength = 30),
"lastName" -> nonEmptyText(minLength = 2, maxLength = 40),
"email" -> email,
"roleAssignmentIds" -> seq(text)
)(UserFormData.apply)(UserFormData.unapply)
)
val roleAssignmentOptions : List[(String, String)] = List("1" -> "Admin", "2" -> "Manager", "3" -> "Service Desk", "4" -> "Jack of All Trades")
然后在您的播放模板中:
@helper.inputCheckboxGroup(form("roleAssignmentIds"), roleAssignmentOptions)
这将显示一个复选框列表。选中复选框时,ID(“1”..“4”)将被发送回服务器。 (如果您提前填写表格,您还需要填写ID - “1”..“4”。)
我有...
- a
Seq[RoleId]
定义用户可以获得的所有角色 - a
User
with a 属性roles: Seq[RoleId]
,其中角色是用户已被授予的角色 - 一个 Play 控制器准备一个表单并将用户(包括她的角色)和可用 RoleId 的 Seq 作为表单数据的一部分(包括映射)提供给 html 页面
- 一个显示每个可用角色复选框的 Twirl 模板
我想要实现的是一个复选框列表,其中每个值属于用户角色的复选框都被选中。因此该列表应该显示哪些可用角色被授予用户,如这个非常精致的原型所示:
Name: [Doe, John]
Roles: [ ] Admin
[x] Manager
[x] Service Desk
[ ] Jack of all trades
如果用户名为 John Doe
,角色为 Manager
和 Service Desk
。
这看起来很简单,但我无法找到一种方法来实现它而不需要一些技巧(比如绕过表单并将角色日期作为常规参数移动到 Twirl 模板;在表单中编写自定义映射器处理代码等)。没有所有样板文件,有没有办法以 Play 方式做到这一点?
我用谷歌搜索,但找不到任何似乎正确的例子。 Play 的表单处理文档也没有帮助。
有什么想法吗?
在完善我的问题后,我想出了一个有效的解决方案。
我使用下面的形式,它使用下面的案例 类 来保存它的数据。如您所见,内部有一个嵌套映射,表示角色列表及其与用户角色相关的状态(true 表示用户拥有该角色,否则为 false):
def userForm(implicit messages: Messages): Form[UserFormData] = Form(
mapping(
"firstName" -> nonEmptyText(minLength = 2, maxLength = 30),
"lastName" -> nonEmptyText(minLength = 2, maxLength = 40),
"email" -> email,
"roleAssignments" -> seq(
mapping(
"roleIdStr" -> nonEmptyText,
"isAssigned" -> boolean
)(RoleAssignment.apply)(RoleAssignment.unapply)
)
)(UserFormData.apply)(UserFormData.unapply)
)
case class UserFormData(firstName: String, lastName: String, email: String, roleAssignments: Seq[RoleAssignment])
case class RoleAssignment(roleIdStr: String, isAssigned: Boolean)
控制器只是用数据库中的数据填充表单:
def user(id: Long) = Action.async { implicit request =>
managerService.retrieveByIdWithRoles(id, Some(request.identity), request.remoteAddress).map { case (user, roles) =>
Ok(views.html.admin.administration.show_user(
userForm.fill(UserFormData(user.firstName, user.lastName, user.email, roleAssignments(roles)))))
}
}
private def roleAssignments(roles: Seq[Role]) = {
val roleIds = roles.map(_.id)
Roles.all.map { case id =>
RoleAssignment(id.toString, roleIds.contains(id))
}
}
并且在视图模板中我重复了 roleAssignments 并使用 repeatWithIndex
提供的索引来访问 seq 的元素:
@repeatWithIndex(userForm("roleAssignments")) { (roleAssignment, index) =>
@b4.checkbox(userForm(s"roleAssignments[$index].isAssigned"), '_text -> userForm(s"roleAssignments[$index].roleIdStr").value, '_custom -> true, 'readonly -> true)
}
谢谢@cchantep 鼓励我更加努力。
Play 库提供了一个 inputCheckboxGroup,其工作方式与 inputRadioGroup 相同。
在您的 Play 控制器中:
def userForm(implicit messages: Messages): Form[UserFormData] = Form(
mapping(
"firstName" -> nonEmptyText(minLength = 2, maxLength = 30),
"lastName" -> nonEmptyText(minLength = 2, maxLength = 40),
"email" -> email,
"roleAssignmentIds" -> seq(text)
)(UserFormData.apply)(UserFormData.unapply)
)
val roleAssignmentOptions : List[(String, String)] = List("1" -> "Admin", "2" -> "Manager", "3" -> "Service Desk", "4" -> "Jack of All Trades")
然后在您的播放模板中:
@helper.inputCheckboxGroup(form("roleAssignmentIds"), roleAssignmentOptions)
这将显示一个复选框列表。选中复选框时,ID(“1”..“4”)将被发送回服务器。 (如果您提前填写表格,您还需要填写ID - “1”..“4”。)