玩Scala中的复选框列表

时间:2019-03-21 19:42:40

标签: forms scala playframework playframework-2.6

我有...

  • Seq[RoleId]定义了用户可以授予的所有角色
  • 具有属性User的{​​{1}},其中角色是授予用户的角色
  • 一个Play控制器准备一个表单,并向用户(包括她的角色)和html页面的可用RoleId的Seq作为表单数据(包括映射)的一部分提供
  • 一个Twirl模板,其中显示了每个可用角色的复选框

我想要实现的是一个复选框列表,其中选中了每个复选框(其值是用户角色的一部分)。因此,该列表应显示授予用户哪些可用角色,如以下非常完善的原型所示:

roles: Seq[RoleId]

如果用户名为Name: [Doe, John] Roles: [ ] Admin [x] Manager [x] Service Desk [ ] Jack of all trades ,且角色分别为John DoeManager

这似乎很简单,但是我没有找到一些技巧就无法找到实现方法(例如绕过表单并将角色日期作为常规参数移动到Twirl模板;在表单处理代码中编写自定义映射器等等。)。没有所有样板就没有办法在Play方式中做到这一点吗?

我努力地搜索过Google,但找不到任何看起来正确的例子。 Play的表单处理文档也没有帮助。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

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”-。)

答案 1 :(得分:0)

在完善我的问题后,我想出了一个可行的解决方案。

我使用以下形式,该形式使用下面的案例类保存其数据。如您所见,内部有一个嵌套的映射,表示角色列表及其相对于用户角色的状态(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)

控制器仅使用来自db的数据填充表单:

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促使我努力尝试。