Frage

So for a system I am developing I am trying to do something similar to this:

If I have a Model called User, that has an _id (ObjectId), username, password, and then I am trying to create a new appointment, my form would look for a patient (display the patient name in the dropdown but really would pick up the patient's ObjectId), and appointment time.

Now I've looked everywhere and can't find anything remotely close to the solution i'm trying to attain.

In Application.scala, I have:

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

I am not sure how to quite work my view in order to reflect the patient. I know you have to do something like this:

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

Can anyone give me any ideas as to how I can look up the patients for this example to pick up a Mongo ObjectId.

The ORM I am using btw is https://github.com/leon/play-salat

War es hilfreich?

Lösung

here is an example how I would do it:

routes:

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

view:

@(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!">
}

controller:

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))
      })
  }
}

Andere Tipps

Fyi, I was able to finally solve the problem after seeing this wonderful comment by maxmc. It turns out my problem was really a fundamental scala issue. I did not realize that List is an implementation of Seq. so using Mongo, in this example, what you have to do is in your code is the following:

CONTROLLER

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

View:

@(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"
    )

the Model.findAll function returns Iterator[Type]. We don't want that. We need to retrieve a list that we can traverse inside the view. That's why you do findAll.toList . From there, the @select will map the pList and for each entry from the database have the id be associated to the patient name. Note that it is a string, because the Seq for the @Select tag requires Seq(String, String)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top