【问题标题】:Checkbox lists in Play with ScalaPlay with Scala 中的复选框列表
【发布时间】:2019-03-21 19:42:39
【问题描述】:

我有...

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

我想要实现的是一个复选框列表,其中每个复选框的值都是用户角色的一部分。所以列表应该显示哪些可用角色被授予用户,如这个非常精致的原型所示:

Name:  [Doe, John]
Roles: [ ] Admin
       [x] Manager
       [x] Service Desk
       [ ] Jack of all trades

如果用户名为John Doe,角色为ManagerService Desk

这看起来相当简单,但如果没有一些技巧,我找不到实现它的方法(比如绕过表单并将角色日期作为常规参数移动到 Twirl 模板;在表单处理代码中编写自定义映射器ETC。)。没有那些样板,难道没有办法以 Play 方式做到这一点吗?

我用谷歌搜索了一番,但找不到任何似乎正确的例子。 Play 的表单处理文档也没有帮助。

有什么想法吗?

【问题讨论】:

  • 如果您想获得帮助,您需要更具体地了解问题所在,错误是什么。

标签: forms scala playframework playframework-2.6


【解决方案1】:

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

我使用下面的表格,它使用下面的案例类来保存它的数据。如您所见,内部有一个嵌套映射,表示角色列表及其与用户角色相关的状态(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 推动我更加努力。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-27
      • 2015-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多