斯卡拉玩!带有 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 个单选按钮的表单验证的主要内容,如果未能解决你的问题,请参考以下文章