斯卡拉玩!带有 2 个单选按钮的表单验证

Posted

技术标签:

【中文标题】斯卡拉玩!带有 2 个单选按钮的表单验证【英文标题】:Scala Play! Form Validation With 2 Radio Buttons 【发布时间】: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 
)
  

任何帮助将不胜感激!

提前致谢!

【问题讨论】:

【参考方案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() = Actionimplicit 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))

【讨论】:

以上是关于斯卡拉玩!带有 2 个单选按钮的表单验证的主要内容,如果未能解决你的问题,请参考以下文章

如何在单选按钮后显示验证消息?

Rails 5 ajax 表单:单击 Ajax 中的 2 个单选按钮之一提交表单

验证 2 组或更多组单选按钮,每组包含 4 个单选按钮

表单验证失败后表单上的单选按钮无法正确呈现 - 引导

绕过表单验证

角度材料单选按钮默认选中不验证表单