Form binding <select multiple> to List in Play framework - scala

I have a ticketing form that simplified contains a "subject" text field, a "content" textarea and a "to" multiple select.
I expected a multiple select to be able to bind to list(uuid) in Play's form mapping, but that is not the case.
request.body.asFormUrlEncoded("to") returns a Vector of several elements but .to in my mapping is empty. Looking at the source code it seems that Play requires me to put the "to" elements in to[0], to[1] etc. But for a multiple select that would be very inconvenient. Is there a better way?
case class CreateTicketFormModel(subject: String, content: String, to: List[UUID])
def CreateTicketForm = Form(mapping(
"subject" -> nonEmptyText,
"content" -> nonEmptyText,
"to" -> list(uuid)
)(CreateTicketFormModel.apply)(CreateTicketFormModel.unapply))

Related

Compare pair of attributes using "IN"

The domain that I'm describing is not the same that I use (with this in mind, there is no need to worry with the fact the the sample class doesn't use Enum for the type, and other things), but describe well my problem. I want to make a query that filter transactions by username and type.
public class Transaction {
private String userName;
private String type;
private BigDecimal value;
...
}
I would like to search all the transactions that match a list of [{'username', 'type'}], where the couple {"username", "type"} is chosen by the user, and the user can choose as many as he wants
For instance: Find all :
"Debit" transactions made by "Rafael"
"Credit" transactions made by "Daniel"
"Debit" transactions made by "Monica"
"Credit" transactions made by "Monica"
I have two possible solutions for my problem, but I don't like any
POSSIBLE SOLUTION 1
I could dynamically add n "OR" clauses to my query, like:
"WHERE (t.userName = 'Rafael' AND t.type = 'Debit')
OR (t.userName = 'Daniel' AND t.type = 'Credit')
... "
POSSIBLE SOLUTION 2
I could concatenate the "username" to the "type" and check if the result is contained by a list of concatenated values of "username" with "type" which was generated dynamically.
CONCAT(t.userName, '-', t.type) IN (list)
for the example, the variable "list" would have the following values:
['Rafael-Debit', 'Daniel-Credit', 'Monica-Debit', 'Monica-Credit']
I'm using JPA, does anyone have a suggestion?

Scala Play Forms verify that one date occurs after another

My form has two dates, but I want to validate that the second date occurs after the first date. Is there a concise way to do this using Play's Form verification?
Here is the form I am working with:
val policyForm: Form[PolicyForm] = Form(mapping(
"amount" -> of[Double].verifying("You need to enter in the amount of bitcoins", _ > 0),
"beginDate" -> date("yyyy-MM-dd").verifying("You cannot have a start date before today", dayLater _ ),
"endDate" -> date("yyyy-MM-dd").verifying("End date has be after the start date", { d =>
???
})
)(PolicyForm.apply _)(PolicyForm.unapply _))
You can't reference other form fields within the same mapping until after they all successfully bind individually. That is, the constraint must be made on the outer mapping.
val policyForm: Form[PolicyForm] = Form {
mapping(
"amount" -> of[Double].verifying(...),
"beginDate" -> date("yyyy-MM-dd").verifying(...),
"endDate" -> date("yyyy-MM-dd")
)(PolicyForm.apply _)(PolicyForm.unapply _).verifying("End date has be after the start date", policyForm =>
policyForm.beginDate.before(policyForm.endDate)
)
}
This assumes java.util.Date, so replace with your own logic if you're using joda time, or something else.

Form mapping that handles optional fields with custom validation

My form looks like:
case class RegistrationForm(department: Option[String], name: String, email: String, employeeId: Option[Int])
Now what I need to do is, if the user entered the department input, then employeeId should be None. And if they left the department empty, then employeeId will be a required field.
My mapping is currently this but it doesn't handle this logic:
val registrationForm = Form(
mapping(
"department" -> optional(String)
"name" -> nonEmptyText,
"email" -> nonEmptyText,
"employeeId" -> optional(number)
)(RegistrationForm.apply)(RegistrationForm.unapply)
)
Also, in my form, how do I create a hidden input field and bind it to my form property, because sometimes my url will be like:
/users/register?employeeId=293838
So I want to create:
<input type="hidden" name="employeeId" value="???" />
So this employeeId hidden input should be bound to the form.
You can use verifying to build constraints between form fields after they've all successfully been bound to the case class.
val registrationForm = Form(
mapping(
"department" -> optional(String)
"name" -> nonEmptyText,
"email" -> nonEmptyText,
"employeeId" -> optional(number)
)(RegistrationForm.apply)(RegistrationForm.unapply)
.verifying("Some error message..", reg =>
(reg.department.isEmpty || reg.employeeId.isEmpty) && (reg.department.nonEmpty || reg.employeeId.nonEmpty)
)
)
The first argument of verifying is an error message to use when the constraint is broken, and the second is a function of the case class you're binding to that returns Boolean. If the function returns false, the Form will contain a global error. I'm not 100% sure that's the logic you're going for in my example, as your wording is a bit strange (sounds like you're describing exclusive OR). You can also chain multiple verifying operations together if needed.
I'm not sure what your question about hidden fields is asking. A hidden field within the html form will be sent to the server with everything else, and bind just as any other field will.

Dependent validation for form mapping in play framework 2

Can I create mapping for form, where first validation depend from second value?
val orderForm = Form(
mapping(
"requiredDelivery" -> boolean,
"deliveryAddress" -> text,
"comment" -> text)
(Order.apply)(Order.unapply)
)
I want to check deliveryAddress for nonEmptyText if requiredDelivery is true
Try:
val orderForm = Form(
mapping(
"requiredDelivery" -> boolean,
"deliveryAddress" -> text,
"comment" -> text)
(Order.apply)(Order.unapply) verifying("Address is required!", fields => fields match {
case order => (order.requiredDelivery && order.deliveryAddress!="") || !order.requiredDelivery
})
)
Any form validation error that is a result from the "verifying" clause after the mapping definition goes into the "global errors". The form helpers won't display these errors, so any typical template will come up blank but not able to successfully submit the form.
The fix is to add something like this to your form template:
#if(userForm.hasGlobalErrors) {
<ul>
#for(error <- userForm.globalErrors) {
<li>#error.message</li>
}
</ul>
}
You can learn more by looking at this page and skipping to the "Display errors in a view template" section - http://www.playframework.com/documentation/2.3-SNAPSHOT/ScalaForms

(Lift) What's the purpouse of dflt : Box[String] parameter in JsCmds.ReplaceOptions case class

There's a case class in JsCmds named ReplaceOptions. The signature of it's constructor is:
ReplaceOptions (select: String, opts: List[(String, String)], dflt: Box[String]) extends JsCmd with Product
And the scaladoc description provided is:
Update a Select with new Options
select: is the id of the select html component that will be updated
opts: is a List with tuples that represents the value:text of the
options that will be set in the select component.
What is dflt intended for? If I simply use Box[String]("Test") it works but I just cant get why.
I think that it is meant to select the default value of the select. For exemple if you update the options to be List(("choice1", "Apple"), ("choice2", "Orange"), ("choice3", "Banana")).
Then you can choose either "Apple", "Orange" or "Banana" as default value by respectively setting dflt as Full("choice1"), Full("choice2") or Full("choice3").
This way, when the user loads the page (or in the case of ReplaceOptions, when the options are replaced), an adapted default value is selected.