【问题标题】:Scala Play! Form Validation With 2 Radio Buttons斯卡拉玩!带有 2 个单选按钮的表单验证
【发布时间】:2018-01-25 22:34:10
【问题描述】:

我创建了一个 Scala Play 程序,并希望将两个单选按钮合并到同一个表单中。

  • 加载页面时,两个单选按钮都没有设置值。
  • 两个单选按钮的选项都是“是”或“否”。

我想知道如何验证两个无线电,以便 Play 在以下情况下接受表单:

  • 只选择第一个无按钮

  • 选择第一个是和第二个是或否按钮。

我希望使用 bindFromRequest.fold 方法显示错误的任何其他情况。

这是我的模型:

    package viewmodels

case class YesNoRadioViewModel2(firstRadio: String, secondRadio:String) {

}

/**
  * View model for pages with yes/no style radio questions.
  */
object YesNoRadioViewModel2 {
  def apply(form: play.api.data.Form[YesNoRadioViewModel2]) = {
    new YesNoRadioViewModel2(
      form.data.get("firstRadio").get,
      form.data.getOrElse("secondRadio","no"))
  }
}

这是我的表格:

val yesNoRadioForm2 = Form(
mapping(
  "firstRadio" -> text.verifying(!_.isEmpty),
  "secondRadio" -> text.verifying()
)
(YesNoRadioViewModel2.apply)(YesNoRadioViewModel2.unapply))

这是我的控制器:

def twoRadioPost: Action[AnyContent] = MyCustomAction.async { implicit request =>

  yesNoRadioForm2.bindFromRequest.fold(formWithErrors =>
  Future(BadRequest(views.html.myproject.twoRadios(formWithErrors)))
    ,
    model =>
   Do something 
)
  }

任何帮助将不胜感激!

提前致谢!

【问题讨论】:

    标签: forms scala validation playframework radio-button


    【解决方案1】:

    我使用 Play 2.6.3

    这里是index.scala.html

    @import models.MyForm.FormData
    @(theForm:Form[FormData])(implicit messages: Messages, request:RequestHeader)
    
    @main("Welcome to Play") {
      <h1>Welcome to Play!</h1>
      @if(theForm.hasGlobalErrors) {
        <ul>
        @for(error <- theForm.globalErrors) {
          <li>@error.format</li>
        }
        </ul>
      }
      @helper.form(action = helper.CSRF(routes.HomeController.processForm())){
        @helper.inputRadioGroup(theForm("field1"), Seq("Yes" -> "Yes", "No" -> "No"))
        @helper.inputRadioGroup(theForm("field2"), Seq("Yes" -> "Yes", "No" -> "No"))
        <button type="submit">Send</button>
      }
    }
    

    这里是MyForm 定义在models 包中的对象:

    package models
    
    import play.api.data.Form
    import play.api.data.Forms._
    
    /**
      * Created by alex on 8/17/17.
      */
    object MyForm {
      case class FormData(firstYesNo:Option[String], secondYesNo:Option[String])
    
      val theForm = Form(
        mapping(
          "field1" -> optional(text),
          "field2" -> optional(text)
        )(FormData.apply)(FormData.unapply) verifying(
            "Form failed the validation",
            fields => fields match{
              case formData => formData.firstYesNo match{
                case None => false
                case Some("No") => if(!formData.secondYesNo.isDefined) true else false
                case Some("Yes") => if(formData.secondYesNo.isDefined) true else false
              }
            }
          )
      )
    }
    

    这是我唯一的控制器的代码:

    import javax.inject._
    import models.MyForm.theForm
    import play.api.mvc._
    
    /**
     * This controller creates an `Action` to handle HTTP requests to the
     * application's home page.
     */
    @Singleton
    class HomeController @Inject()(cc: ControllerComponents) extends AbstractController(cc) with play.api.i18n.I18nSupport{
    
      /**
       * Create an Action to render an HTML page.
       *
       * The configuration in the `routes` file means that this method
       * will be called when the application receives a `GET` request with
       * a path of `/`.
       */
      def index() = Action { implicit request: Request[AnyContent] =>
        Ok(views.html.index(theForm))
      }
    
      def processForm() = Action{implicit request:Request[AnyContent] =>
        theForm.bindFromRequest().fold(
          formWithErrors => BadRequest(views.html.index(formWithErrors)),
          data => Ok("Form successfully submitted")
        )
      }
    }
    

    我的routes 文件的内容:

    GET     /                           controllers.HomeController.index
    
    POST    /processForm                controllers.HomeController.processForm
    
    # Map static resources from the /public folder to the /assets URL path
    GET     /assets/*file               controllers.Assets.versioned(path="/public", file: Asset)
    

    最后,我们需要将其添加到application.conf

    play.filters.enabled += play.filters.csrf.CSRFFilter

    希望对你有所帮助。

    【讨论】:

    • 太棒了,谢谢!出于兴趣,用两种不同的形式嵌套 .bindFromRequest().fold 是不好的做法吗?谢谢
    • 我从未尝试过这个。 POST 请求在其主体中嵌入了一个表单数据,但我可以想象如果需要,可以尝试在控制器中将其绑定到两个不同的模型:)
    • 我试过了,效果很好。只要这不是常见的不良做法,我应该没问题。非常感谢,非常感谢
    • 如果我的回答对你有帮助,那你可以接受吗?
    【解决方案2】:

    最后我创建了两个不同的表单并使用它们来验证单选按钮。

    我的控制器

    Form1.bindFromRequest.fold(
      formWithErrors => Future(BadRequest(views.html.myproject.form(formWithErrors,Form2)))
      ,
      model =>
        if(model.radioName.equals("yes")){
          Form2.bindFromRequest.fold(
            formWithErrors => Future(BadRequest(views.html.myproject.form(Form1,formWithErrors)))
            ,
            model =>
              if(model.radioName.equals("yes")){
                Future(Ok(GOSOMEWHERE()))
              }else{
                Future(Ok(GOSOMEWHERE()))
              })
        }else{ Future(Ok(GOSOMEWHERE())) })
    

    我的表格

    val Form1 = Form(
    mapping(
      "firstRadio" -> text.verifying(!_.isEmpty)
    )
    (YesNoRadioViewModel.apply)(YesNoRadioViewModel.unapply))
    
    
    
    val Form2 = Form(
    mapping(
      "secondRadio" -> text.verifying()
    )
    (YesNoRadioViewModel.apply)(YesNoRadioViewModel.unapply))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-17
      • 2019-08-18
      • 2016-04-22
      • 1970-01-01
      • 2011-06-07
      • 2023-04-01
      • 2014-07-06
      • 2012-07-16
      相关资源
      最近更新 更多