玩!从单独的mongo集合中选择项目的表单

时间:2012-08-09 19:13:23

标签: scala mongodb playframework playframework-2.0 salat

因此,对于我正在开发的系统,我正在尝试做类似的事情:

如果我有一个名为User的模型,它有一个_id(ObjectId),用户名,密码,然后我正在尝试创建一个新约会,我的表单将寻找一个患者(在下拉列表中显示患者姓名但是真的会拿起患者的ObjectId)和预约时间。

现在我到处寻找,找不到任何与我想要达到的解决方案相近的东西。

在Application.scala中,我有:

val appointmentForm= Form(
  tuple(
    "patient" -> nonEmptyText, // ObjectId
    "startTime" -> nonEmptyText))

我不确定如何完善我的观点以反映患者。我知道你必须这样做:

@select(appointmentForm("patient"), options(..)

任何人都可以给我任何想法,我可以如何查看这个例子中的患者来获取Mongo ObjectId。

我使用btw的ORM是https://github.com/leon/play-salat

2 个答案:

答案 0 :(得分:1)

这是我将如何做的一个例子:

路线:

GET      /test        controllers.Test.show
POST     /test        controllers.Test.submit

视图:

@(f: Form[(ObjectId, String)], users: Seq[(ObjectId, String)])
@import helper._

@form(action = routes.Test.submit) {
  @select(f("patient"), options = users.map(user => (user._1.toString, user._2)))
  @inputText(f("startTime"))
  <input type="submit" value="Submit!">
}

控制器:

package controllers

import org.bson.types.ObjectId
import play.api.data.format.Formatter
import play.api.mvc._
import play.api.data.Forms._
import play.api.data._
import play.api.data.FormError
import play.api.Logger

object Test extends Controller {

  /**
   * Converts an ObjectId to a String and vice versa
   */
  implicit object ObjectIdFormatter extends Formatter[ObjectId] {
    def bind(key: String, data: Map[String, String]) = {
      val error = FormError(key, "error.required.ObjectId", Nil)
      val s = Seq(error)
      val k = data.get(key)
      k.toRight(s).right.flatMap {
        case str: String if (str.length() > 0) => Right(new ObjectId(str))
        case _ => Left(s)
      }
    }
    def unbind(key: String, value: ObjectId) = Map(key -> value.toStringMongod())

    val objectId: Mapping[ObjectId] = of[ObjectId]
  }

  // import to get objectId into scope
  import ObjectIdFormatter._

  // define user tuples consisting of username and ObjectId for the dropdown. In real lif the list is probably fetched from the db
  def users: Seq[(ObjectId, String)] =
    Seq((new ObjectId("4f456bf744aed129d04db1bd"), "dieter"), (new ObjectId("4faa410b44aec5a0a980599f"), "eva"))

  val appointmentForm= Form(
    tuple(
      "patient" -> objectId, // use the ObjectIdFormatter
      "startTime" -> nonEmptyText))


  def show = Action {
    Ok(views.html.test(appointmentForm, users))
  }

  def submit = Action { implicit request =>
    appointmentForm.bindFromRequest.fold(
      formWithErrors => {
        Logger.warn("errors: " + formWithErrors.errors)
        BadRequest(views.html.test(formWithErrors, users))
      },
      formContent => {
        Logger.info("formContent: " + formContent)
        Ok(views.html.test(appointmentForm, users))
      })
  }
}

答案 1 :(得分:0)

Fyi,看到maxmc的精彩评论后,我终于解决了这个问题。事实证明我的问题确实是一个基本的scala问题。我没有意识到List是Seq的一个实现。所以使用Mongo,在这个例子中,你需要做的就是你的代码如下:

CONTROLLER

 def newAppointment= Action {
   val pList  = Patient.findAll.toList
   Ok(views.html.admin.newuser(appointmentForm, pList))
 }

查看:

@(appointmentForm: Form[(String, String, String)], pList : List[Patient])

... ... ...

@select(
        appointmentForm("patient"),
        pList.map{ p =>
            p.id.toString -> (p.patientName)
        },
        '_default -> "--- Select a Patient ---",
        '_label -> "Patient"
    )

Model.findAll函数返回Iterator [Type]。我们不希望这样。我们需要检索一个可以在视图中遍历的列表。这就是你做findAll.toList的原因。从那里,@ select将映射pList,并且对于数据库中的每个条目,id都与患者姓名相关联。请注意,它是一个字符串,因为@Select标记的Seq需要Seq(String,String)