Overloaded method value [apply] cannot be applied to (play.api.data.Mapping[String]) - scala

I am studying to use play and scala to build a web app, and have some problem with checkbox post.
My controller:
val serviceForm = Form(tuple(
"id" -> number,
"name" -> text,
"checkboxList" -> list(text)
)
)
And my html
<form action="/testCheckbox" method="POST">
<input type="text" name="id">
<input type="text" name="name">
<input type="checkbox" name="checboxList[]"> cb1
<input type="checkbox" name="checboxList[]"> cb2
<input type="checkbox" name="checboxList[]"> cb3
..
</form>
POST DATA(from chrome debug tools):
id: 1
name: test
checkboxList[]: 1
checkboxList[]: 2
checkboxList[]: 2
Then play says [web]:
Overloaded method value [apply] cannot be applied to (play.api.data.Mapping[String])
console:
overloaded method value apply with alternatives:
[error] (rh: play.api.mvc.RequestHeader)play.api.libs.iteratee.Iteratee[Array[Byte],play.api.mvc.SimpleResult] <and>
[error] (request: play.api.mvc.Request[play.api.mvc.AnyContent])scala.concurrent.Future[play.api.mvc.SimpleResult]
[error] cannot be applied to (play.api.data.Mapping[String])
[error] "checkboxList" -> list(text)
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
What is the problem?

Related

Scala Play: How to render Form mappings with Repeated and Nested values?

I'm working on a Scala Play 2.7.x (you may checkout the project here play-silhouette-seed googleauth branch) and I have a form defined as:
object TotpSetupForm {
val form = Form(
mapping(
"sharedKey" -> nonEmptyText,
"scratchCodes" -> seq(mapping(
"hasher" -> nonEmptyText,
"password" -> nonEmptyText,
"salt" -> optional(nonEmptyText)
)(PasswordInfo.apply)(PasswordInfo.unapply)),
"scratchCodesPlain" -> optional(seq(nonEmptyText)),
"verificationCode" -> nonEmptyText(minLength = 6, maxLength = 6)
)(Data.apply)(Data.unapply)
)
case class Data(
sharedKey: String,
scratchCodes: Seq[PasswordInfo],
scratchCodesPlain: Option[Seq[String]],
verificationCode: String = "")
}
Where PasswordInfo comes from Play-Silhouette and looks like:
case class PasswordInfo(
hasher: String,
password: String,
salt: Option[String] = None
) extends AuthInfo
In my controller I populate the form and pass it as parameter to my view template as follows. Note that I have debugged it and totpInfo.scratchCodes has 5 values and the form is correctly populated:
val formData = TotpSetupForm.form.fill(TotpSetupForm.Data(totpInfo.sharedKey, totpInfo.scratchCodes, totpInfo.scratchCodesPlain))
Ok(views.html.someView(formData, ...)
I render the view as follows, please note that I did read the Scala Forms Repeated Values documentation note :)
#helper.form(action = controllers.routes.TotpController.submit()) {
#helper.CSRF.formField
#b3.text(totpForm("verificationCode"), '_hiddenLabel -> messages("verificationCode"), 'placeholder -> messages("verificationCode"), 'autocomplete -> "off", 'class -> "form-control input-lg")
#b3.hidden(totpForm("sharedKey"))
#helper.repeatWithIndex(totpForm("scratchCodes"), min = 1) { (scratchCodeField, index) =>
#b3.hidden(scratchCodeField, '_label -> ("scratchCode #" + index))
}
<div class="form-group">
<div>
<button id="submit" type="submit" value="submit" class="btn btn-lg btn-primary btn-block">#messages("verify")</button>
</div>
</div>
}
even though the form's scratchCodes sequence is correctly populated, each of the sequence values render as empty:
<input type="hidden" name="scratchCodes[0]" value="" >
<input type="hidden" name="scratchCodes[1]" value="" >
<input type="hidden" name="scratchCodes[2]" value="" >
<input type="hidden" name="scratchCodes[3]" value="" >
<input type="hidden" name="scratchCodes[4]" value="" >
The number of fields in the sequence is correct though.
I have also tried using the #helper.repeat alternative and even using the #helper.input instead of #b3.hidden just to be sure and the result is always the same ... I get empty valued PasswordInfo tuples rendered.
How can I fix this?
OK found the culprit: repeated + nested values require accessing each attribute separately like this:
#helper.repeat(totpForm("scratchCodes"), min = 1) { scratchCodeField =>
#b3.hidden(scratchCodeField("hasher"))
#b3.hidden(scratchCodeField("password"))
#b3.hidden(scratchCodeField("salt"))
}
then works fine and the post request populates the sequence of PasswordInfo UDTs correctly.

Selenium-IDE error on type command

I need to enter a username in form field, but get an error. Here is the html-code:
<input class="_kp5f7 _qy55y" aria-describedby=""
aria-label="User name" aria-required="true" autocapitalize="off"
autocorrect="off" maxlength="30" name="username"
placeholder="User name" value="tst666444" type="text">
There's no id. How to build a command? I use the command type.
Command: type
Target: name=username
Value: tst666444
In log - error:
[error] Element name=username not found
[info] Test case failed

Nested form in Play! Scala 2.2

I have read several times the documentation but I still have problems with my nested form in Play! Scala 2.2 (detailed further).
Here is my form :
<form method="post" action="/admin/test2">
first name : <input type="text" name="firstname"> <br>
info 0 : <input type="text" name="label[0]"> <br>
info 1 : <input type="text" name="label[1]"> <br>
<input type="submit" value="test nested form" />
</form>
And the case classes corresponding :
case class Contact(firstname: String,
informations: Seq[ContactInformation])
case class ContactInformation(label: String)
val contactForm: Form[Contact] = Form(
mapping(
"firstname" -> nonEmptyText,
"informations" -> seq(
mapping(
"label" -> nonEmptyText
)(ContactInformation.apply)(ContactInformation.unapply)
)
)(Contact.apply)(Contact.unapply)
)
def saveContact = Action { implicit request =>
contactForm.bindFromRequest.fold(
formWithErrors => Ok("error"),
contact => {
println(contact)
Ok("Done")
}
)
}
I don't get any errors, but the contact that I get from the form (printed with println(contact)) has an empty informations field, i.e. it looks like this : Contact(h,List())
The error comes probably from the html part since I have followed to the letter the documentation from this page : play! scala forms documentation
but I can’t figure it out.
The field names of the inputs should use the full path in the Form. label appears within the informations Mapping, and informations is the sequence, not the label, so you should use informations[0].label instead of label[0].
Your view should look like this:
first name : <input type="text" name="firstname"> <br>
info 0 : <input type="text" name="informations[0].label"> <br>
info 1 : <input type="text" name="informations[1].label"> <br>

NoSuchElementException: None.get in play framework for scala

I need to build update method, but when i test show the error NoSuchElementException: None.get
UserController
object UserController extends Controller {
def update(id:Long) = DBAction { implicit rs =>
var user = simpleUserForm.bindFromRequest.get
user.id = Users.toOption(id)
Users.update(user)
Redirect(routes.UserController.list)
}
val simpleUserForm :Form[User] = Form {
mapping(
"firstName" -> nonEmptyText,
"lastName" -> nonEmptyText,
"email" -> email,
"birthDate" -> nonEmptyText,
"phone" -> nonEmptyText,
"username" -> text,
"password" -> nonEmptyText
)(UserForm.fromSimpleForm)(UserForm.toSimpleForm)
}
}
edit.scala.html
#import models.auth.Users
#(title: String, user:models.auth.User)
#main(title){
<form method="post" action="#controllers.auth.routes.UserController.update(Users.toLong(user.id))">
<input type="text" placeholder="First Name" name="firstName" value="#user.firstName"/><br/>
<input type="text" placeholder="Last Name" name="lastName" value="#user.lastName"/><br/>
<input type="email" placeholder="Email" name="email" value="#user.email" /><br/>
<input type="text" placeholder="Phone" name="phone" value="#user.phone" /><br/>
<input type="text" placeholder="Birthdate(dd/MM/yyyy)" name="birthDate" value="#user.birthDate" /><br/>
<input type="text" placeholder="Username" name="username" value="#user.username" /><br/>
<input type="submit" value="Update User" />
</form>
}
routes
POST /user/:id/ controllers.auth.UserController.update(id:Long)
I already done for create, read and delete, but for update i found error in line
var user = simpleUserForm.bindFromRequest.get
the error is NoSuchElementException: None.get
The Play page on Scala Forms is helpful here. That approach would be to send the populated form to the view as a parameter, then on submit use fold, which gives you options to deal with the error case as well as the "happy" case. Something like the following (adapted from the above page):
simpleUserForm.bindFromRequest.fold(
formWithErrors => {
// binding failure, you retrieve the form containing errors:
// in your form, test .hasErrors
BadRequest(views.html.user.edit(formWithErrors))
},
userData => {
/* binding success, you get the value. */
// .. do the update
...
//-- and return to list or home or...
Redirect(routes.Application.home(id))
}
)
If you don't want to use the form, then to back to your actual question, would .getOrElse not work?
did you import
import play.api.libs.concurrent.Execution.Implicits._

non understandable error in a twirl file(scala+sbt+spray+twirl)

I have a strange error when I try to compile a spray project whose twirl file is expected to display a list of RDV (meetings) between 2 dates:
> compile
[info] Compiling twirl template .../texte.scala.html to .../texte.template.scala
[info] Compiling 9 Scala sources to /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/target/scala-2.10/classes...
[error] /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/target/scala-2.10/src_managed/main/generated-twirl-sources/html/texte.template.scala:16: ')' expected but '=' found.
[error] Seq[Any](_display_(Seq[Any](/*2.2*/(rdvs:List[Rdv], de:String = "Entrez une date", jusque:String = "Entrez une date"))),format.raw/*2.84*/("""
[error] ^
[error] /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/target/scala-2.10/src_managed/main/generated-twirl-sources/html/texte.template.scala:120: ')' expected but '}' found.
[error] </html>"""))}
[error] ^
[error] two errors found
[error] 2 problem(s) in Twirl template(s) found
[error] /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/src/main/twirl/texte.scala.html:2: ')' expected but '=' found.
[error] #(rdvs:List[Rdv], de:String = "Entrez une date", jusque:String = "Entrez une date")
[error] ^
[error] /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/src/main/twirl/texte.scala.html:108: ')' expected but '}' found.
[error] (compile:compile) Compilation failed
[error] Total time: 1 s, completed 17 mars 2014 19:48:06
After some errors in the twirl compiled file, sbt gives me the corresponding error in the html file, but it's not understandable for me;
here is the twirl file:
#import metier.Objets.Rdv
#(rdvs:List[Rdv], de:String = "Entrez une date", jusque:String = "Entrez une date")
<!-- -->
<html>
<head>
<!-- DataTables CSS -->
<link rel="stylesheet" type="text/css"
href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css">
<!-- jQuery
<script type="text/javascript" charset="utf8"
src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.2.min.js"></script>-->
<link rel="stylesheet"
href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css">
<!-- DataTables -->
<script type="text/javascript" charset="utf8"
src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="https://github.com/jquery/jquery-ui/blob/master/ui/i18n/datepicker-fr.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#aTable').dataTable();
});
</script>
<script>
$(function() {
$.datepicker.setDefaults($.datepicker.regional[""]);
$("#from").datepicker({
dateFormat: 'dd-mm-yy',
changeMonth : true,
changeYear : true,
onClose : function(selectedDate) {
$("#to").datepicker("option", "minDate", selectedDate);
}
});
$("#from").datepicker($.datepicker.regional["fr"]);
$("#to").datepicker({
dateFormat: 'dd-mm-yy',
changeMonth : true,
changeYear : true,
onClose : function(selectedDate) {
$("#from").datepicker("option", "maxDate", selectedDate);
}
});
});
</script>
</head>
#* This template is a simple html template --- (this text btw. is a
comment and is not rendered) *#
<form class="form-horizontal" id="signinForm" action="" method="post">
<label>hello</label> <input name="nom" />
<button data-bind="click: signin">CLICK ME!</button>
<br /> <label for="from">De</label> <input type="text" id="from"
name="from"> <label for="De">à</label> <input type="text"
id="to" name="to">
</form>
<table id="aTable" class="display" width="500px" align="left">
<thead>
<tr>
<th>Nom</th>
<th>Prénom</th>
<th>Date examen</th>
<th>Heure Examen</th>
<th>Tél.</th>
<th>Bureau</th>
<th>Privé</th>
<th>Site</th>
<th>Type</th>
<th>Libellé</th>
<th>orderID</th>
<th>Statut</th>
</tr>
</thead>
<tbody>
#for(rdv <- rdvs){
<tr>
<td>#rdv.nom</td>
<td>#rdv.prénom</td>
<td>#rdv.dateRDV</td>
<td>#rdv.heureRDVString</td>
<td>#rdv.telPortable</td>
<td>#rdv.telBureau</td>
<td>#rdv.telPrivé</td>
<td>#rdv.siteRDV</td>
<td>#rdv.typeRDV</td>
<td>#rdv.libelléRDV</td>
<td>#rdv.orderId</td>
<td>#rdv.statut</td>
</tr>
}
</tbody>
</table>
</html>
only the beginning is concerned by the error.
can you help me?
ps: here is the part of the route treating the form of the previous twirl file:
post {
formField( 'nom ,'from, 'to) { (name,de,jusque) =>
println( "button clicked!" )
respondWithMediaType( `text/html` ) {
val listOfRdv:List[Rdv]=grab_rdv
complete( html.texte(listOfRdv ).toString )
}
}
}
thanks
PS : to answer to the comment, here is the new error when I remove the defaults values:
[
info] Compiling twirl template .../texte.scala.html to .../texte.template.scala
[info] Compiling 9 Scala sources to /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/target/scala-2.10/classes...
[error] /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/src/main/scala/com/example/MyService.scala:43: too many arguments for method apply: ()twirl.api.HtmlFormat.Appendable in object texte
[error] complete( html.texte( Nil ).toString )
[error] ^
[error] /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/src/main/scala/metier/Objets.scala:4: object io is not a member of package reflect
[error] import scala.reflect.io.File
[error] ^
[error] /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/src/main/scala/metier/Objets.scala:124: not found: value File
[error] val fileToSave = File(fileString)
[error] ^
[error] /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/src/main/scala/metier/Objets.scala:127: not found: value File
[error] val ancientFile = File(fileString + ".save")
[error] ^
[error] /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/target/scala-2.10/src_managed/main/generated-twirl-sources/html/texte.template.scala:16: not found: value rdvs
[error] Seq[Any](_display_(Seq[Any](/*2.2*/(rdvs:List[Rdv], de:String, jusque:String ))),format.raw/*2.45*/("""
[error] ^
[error] 5 errors found
[error] 1 problem(s) in Twirl template(s) found
[error] /Users/oliviersaint-eve/sms/SPRAY/spray-macaque/src/main/twirl/texte.scala.html:2: not found: value rdvs
[error] #(rdvs:List[Rdv], de:String, jusque:String )
[error] ^
[error] (compile:compile) Compilation failed
[error] Total time: 9 s, completed 17 mars 2014 20:56:12
Again, it's incomprehensible, in my routes either I call the page with the parameter of type List[Rdv] or with Nil...
It seems like you cannot have default values in your template parameters. Try changing the second line like this:
#(rdvs: List[Rdv], de: String, jusque: String)
You can pass these values instead of keeping them as default ones.