在Play 2.5中使用Scalaform映射select输入-使用DTO对象
我在Play2.5中有以下控制器,取自github repo raul782/play commerce在Play 2.5中使用Scalaform映射select输入-使用DTO对象,scala,playframework,Scala,Playframework,我在Play2.5中有以下控制器,取自github repo raul782/play commerce class CategoryController(implicit inj: Injector) extends Controller { private val categoryService = inject[CategoryService] def viewAllCategories = Action { implicit request => val all
class CategoryController(implicit inj: Injector) extends Controller {
private val categoryService = inject[CategoryService]
def viewAllCategories = Action { implicit request =>
val allCategories = categoryService.findAll.map(Category.toDTO(_))
Ok(views.html.product.categoryList(allCategories))
}
def listCategories = Action { implicit request =>
val allCategories = categoryService.findAll.map(Category.toDTO(_))
Ok(RequestUtil.toJsonString(allCategories)).as(JSON)
}
def viewCategoryForm(categoryId: Long) = Action { implicit request =>
Ok(views.html.product.category(views.forms.product.categoryForm, categoryService.findAll))
}
def addCategoryForm = Action { implicit request =>
Ok(views.html.product.category(views.forms.product.categoryForm, categoryService.findAll))
}
def addCategory = Action { implicit request =>
import views.forms.product.categoryForm
categoryForm.bindFromRequest.fold(
formWithErrors => {
Ok(views.html.product.category(formWithErrors, categoryService.findAll))
},
categoryDTO => {
play.Logger.debug(request.body.asFormUrlEncoded.toString)
play.Logger.debug(categoryDTO.toString)
val category = Category.fromDTO(categoryDTO)
categoryService.save(category)
Redirect(routes.CategoryController.viewAllCategories())
}
)
}
}
我的category.html.scala设置为:
@(categoryForm: Form[dtos.product.CategoryDTO], categoryDTOs: Seq[models.product.Category])(implicit request: play.api.mvc.Request[play.api.mvc.AnyContent])
@import models.product.Category
@import helper._
@import views.html.forms.inputHidden
@import views.forms.FormHelpers.bootstrapVerticalFormFieldConstructor
@title = @{categoryForm(Category.Id).value.
map(_ => Messages("forms.categories.update")).
getOrElse(Messages("forms.categories.add"))}
@action = @{categoryForm(Category.Id).value.
map(_ => controllers.product.routes.CategoryController.updateCategory()).
getOrElse(controllers.product.routes.CategoryController.addCategory())}
@categoryOptions = @{categoryDTOs.map(category => category.id.toString -> category.name)}
@main(title = title) {
<div class="col-sm-2">
<h2>@title</h2>
</div>
<div class="col-sm-7">
@form(action = action, args = 'class -> "well") {
@inputHidden(categoryForm(Category.Id))
@inputText(categoryForm(Category.Name), 'class -> "form-control")
@select(categoryForm(Category.ParentCategory), categoryOptions, 'class -> "form-control", '_default -> "--- select ---")
<div class="form-group">
<button type="submit" class="btn btn-primary">
@Messages("forms.save")
</button>
<a href="@controllers.product.routes.CategoryController.viewAllCategories()" class="btn btn-default">@Messages("forms.cancel")</a>
</div>
}
</div>
}
我的分类如下:
package views.forms
import play.api.data._
import play.api.data.Forms._
import dtos.product.CategoryDTO
package object product {
val categoryForm = Form(
mapping(
"id" -> optional(longNumber(strict = true)),
"name" -> text(minLength = 1, maxLength = 255),
"parentCategoryId" -> list(optional(longNumber))
) (CategoryDTO.apply) (CategoryDTO.unapply)
)
}
package dtos.product
case class CategoryDTO(id: Option[Long], name: String, parentCategoryId: List[Option[Long]]) {
var ancestry: Seq[CategoryDTO] = Nil
var parentCategoryName: Option[String] = None
}
package models.product
import models.BaseEntity
import javax.persistence.Entity
import javax.persistence.Column
import javax.persistence.Access
import javax.persistence.AccessType
import java.util.LinkedHashSet
import javax.persistence.ManyToOne
import javax.persistence.OneToMany
import java.util.{Set => JSet}
import models.IdentifierProperty
import dtos.product.CategoryDTO
@Entity
class Category extends BaseEntity {
def this(id: Option[Long]) = {
this()
this.id = id
}
@Column(nullable = false, length = 255)
var name: String = _
@Access(AccessType.PROPERTY)
@ManyToOne(targetEntity = classOf[Category])
var parentCategory: Option[Category] = None
@OneToMany(mappedBy = "parentCategory")
var childCategories: JSet[Category] = new LinkedHashSet
def ancestors = {
traverseAncestry(parentCategory)
}
private def traverseAncestry(parentCategory: Option[Category], lst: List[Category] = Nil): Seq[Category] = {
parentCategory match {
case Some(currentParentCategory) => traverseAncestry(currentParentCategory.parentCategory, currentParentCategory :: lst)
case _ => lst
}
}
protected def getParentCategory() = {
parentCategory.getOrElse(null)
}
protected def setParentCategory(category: Category) {
parentCategory = Option(category)
}
}
object Category extends IdentifierProperty {
val Name = "name"
val ParentCategory = "parentCategoryId"
val ChildCategories = "childCategories"
def toDTO(category: Category, withAncestry: Boolean = false): CategoryDTO = {
val dto = CategoryDTO(category.id, category.name, category.parentCategory.map( c => c.id).toList)
dto.parentCategoryName = category.parentCategory.map(_.name)
dto.ancestry = if(withAncestry) {
category.ancestors.map(Category.toDTO(_))
} else {
Nil
}
dto
}
def fromDTO(dto: CategoryDTO) = {
val category = new Category
category.name = dto.name
category.parentCategory = dto.parentCategoryId match {
case Nil => None
case head::_ => head.map(id => new Category(Some(id)))
}
category
}
}
我的分类模型如下:
package views.forms
import play.api.data._
import play.api.data.Forms._
import dtos.product.CategoryDTO
package object product {
val categoryForm = Form(
mapping(
"id" -> optional(longNumber(strict = true)),
"name" -> text(minLength = 1, maxLength = 255),
"parentCategoryId" -> list(optional(longNumber))
) (CategoryDTO.apply) (CategoryDTO.unapply)
)
}
package dtos.product
case class CategoryDTO(id: Option[Long], name: String, parentCategoryId: List[Option[Long]]) {
var ancestry: Seq[CategoryDTO] = Nil
var parentCategoryName: Option[String] = None
}
package models.product
import models.BaseEntity
import javax.persistence.Entity
import javax.persistence.Column
import javax.persistence.Access
import javax.persistence.AccessType
import java.util.LinkedHashSet
import javax.persistence.ManyToOne
import javax.persistence.OneToMany
import java.util.{Set => JSet}
import models.IdentifierProperty
import dtos.product.CategoryDTO
@Entity
class Category extends BaseEntity {
def this(id: Option[Long]) = {
this()
this.id = id
}
@Column(nullable = false, length = 255)
var name: String = _
@Access(AccessType.PROPERTY)
@ManyToOne(targetEntity = classOf[Category])
var parentCategory: Option[Category] = None
@OneToMany(mappedBy = "parentCategory")
var childCategories: JSet[Category] = new LinkedHashSet
def ancestors = {
traverseAncestry(parentCategory)
}
private def traverseAncestry(parentCategory: Option[Category], lst: List[Category] = Nil): Seq[Category] = {
parentCategory match {
case Some(currentParentCategory) => traverseAncestry(currentParentCategory.parentCategory, currentParentCategory :: lst)
case _ => lst
}
}
protected def getParentCategory() = {
parentCategory.getOrElse(null)
}
protected def setParentCategory(category: Category) {
parentCategory = Option(category)
}
}
object Category extends IdentifierProperty {
val Name = "name"
val ParentCategory = "parentCategoryId"
val ChildCategories = "childCategories"
def toDTO(category: Category, withAncestry: Boolean = false): CategoryDTO = {
val dto = CategoryDTO(category.id, category.name, category.parentCategory.map( c => c.id).toList)
dto.parentCategoryName = category.parentCategory.map(_.name)
dto.ancestry = if(withAncestry) {
category.ancestors.map(Category.toDTO(_))
} else {
Nil
}
dto
}
def fromDTO(dto: CategoryDTO) = {
val category = new Category
category.name = dto.name
category.parentCategory = dto.parentCategoryId match {
case Nil => None
case head::_ => head.map(id => new Category(Some(id)))
}
category
}
}
当我填写表单并提交请求时,表单将被保存,但仅保存名称,而不保存父类别。
我注意到发送的select输入值是一些(15),其中15是parentCategoryId
最初,parentCategoryId的categoryForm映射只是可选的(longNumber),但我也无法捕获值
我切换到list(可选(longNumber)),因为当您使用select输入时,文档会这么说
但是仍然没有运气,没有任何建议,或者我的实现有什么问题
谢谢从您的问题和一个类别只有一个父类别名称的事实判断,我假设您只需要父类别的(单个)id?这是相当典型的“外键”情况。
select
元素(默认情况下)仅选择单个元素
- 在映射中,使用
而不是列表李>可选(longNumber)
- 在数据中,使其成为
而不是集合李>选项[Int]