I'm trying to figure out best practice to bind enum
to form drop-down <select>
in Play! 2.0
Here is my enum:
public enum ContactType {
CLIENT(1),
CONTRACTOR(2),
SUPPLIER(3);
public final int id;
ContactType(int id) {
this.id = id;
}
}
And here's what i'd like to get as result in my view:
<select name="contactType">
<option value="1">CLIENT</option>
<option value="2">CONTRACTOR</option>
<option value="3">SUPPLIER</option>
</select>
Assuming you are putting the select into a HTML form, the way it is done in our shop is we add a Map to the Java enum and then use the select form helper provided by the framework:
enum:
public enum ContactType {
CLIENT(1),
CONTRACTOR(2),
SUPPLIER(3);
public final int id;
ContactType(int id) {
this.id = id;
}
public static Map<String, String> options(){
LinkedHashMap<String, String> vals = new LinkedHashMap<String, String>();
for (ContactTypecType cType: ContactType.values()) {
vals.put(cType.id(), cType.name());
}
return vals;
}
}
view:
@(contactForm: Form[models.Contact])
import helper._
<html><head></head><body>
@helper.form(routes.Contact.formHandlerMethod()){
@*
* Here contactForm("contactType") assumes that you want to map the
* ContactType selected to a field in a Contact class (which we've
* wrapped in play.data.Form<T> so that the fields in Contact become
* inputs in our form
*@
@select(contactForm("contactType"), options(ContactType.options())
}
</body></html>
Using this design pattern you can leverage the helper functions in the play.data.Form class to validate and bind your form data in your Contact Controller and you benefit from having less logic in your view, and putting the logic in a place where it can easily be re-used throughout your app.
If, on the other hand, you are using the select on it's own and driving actions in some other way, then Aerus' answer is probably the most straightforward way.
Something like this in your template should work:
<select name="contactType">
@for(cType <- ContactType.values()){
<option value="@cType.id">@cType.name()</option>
}
</select>
Note: it may be better to use toString()
instead of name()
. If you override toString()
in your enum you could return Contractor instead of CONTRACTOR.
Note 2: if your enum is not in the models
package you need to prefix it with the right package name i.e.: @for(cType <- com.my_company.enums.ContactType)
EDIT: The form should not include all the classpath to the enum, just the enum name. So on the ContactType class, the put method has to be replaced to this:
put(value.name(),name);
I'm not able to bind the enum to the class. In the controller I have something like that:
public Result saveUser() {
Form<User> userForm = form(User.class).bindFromRequest();
if(userForm.hasErrors()) {
return badRequest(createUser.render(userForm));
}
User user=userForm.get();
user.save();
Logger.info(user.contacts.toString());
flash("success", "User " + userForm.get().identity + " has been created");
return GO_ADMIN;
}
Which is returning me all the time "error.invalid". The POST response looks like that:
identity=asas&
status=1&
contacts[0].name=fasddf&
contacts[0].prename=afadfs&
contacts[0][email protected]&
contacts[0].contactType=models.constats.ContactType.MANAGER
Just to have more information, I provide here the User and the Contact classes
User
public class User extends Model{
@Constraints.Required(message = "Field is required")
public String identity;
public Integer status;
@Valid
public List<Contact> contacts;
}
Contact
public class Contact extends Generic{
@Constraints.Required(message = "Field is required")
public String name;
@Constraints.Required(message = "Field is required")
public String prename;
@Constraints.Required(message = "Field is required")
@Constraints.Email
public String email;
public ContactType contactType;
}
ContactType
public enum ContactType {
ADMIN,SUPPORT,MANAGER,DEVELOPER,DESIGNER,NO_INFORMATION;
}
public static final Map<String,Object> types=new HashMap<String,Object>()
{{
for (ContactType value : ContactType.values()) {
String name=value.name().toLowerCase();
name=Character.toUpperCase(name.charAt(0)) + name.substring(1).replaceAll("_", " ");
put(ContactType.class.getName() + "."+ value.name(),name);
}
}};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With