Reputation: 1751
I am new to Play framework, i am trying to save the user info's which is entered by the admin person in view. I am rendering the view with form helper. One of the field in view is drop down box, which allows the user to select the grade level, which has value of grade id and display text has grade name. In my user model i am having field as gradeLevel which is references GradeLevel model. I don't know how to set GradeLevel object when selecting respective grade id from drop down box. Right now it throws Illegal state exception: No value when submitting the form.
Given below the code snippets.
View
@(userForm: Form[UserDetails],gradeMap: HashMap[String,String])
@import helper._
@main("Sample") {
<h1>Add User</h1>
@form(action = routes.UserController.validate()){
@inputText(userForm("firstName"), '_label -> "Firstname",'_showConstraints -> false)
@inputText(userForm("lastName"), '_label -> "Lastname",'_showConstraints -> false)
@select(userForm("gradeLevel"), options(gradeMap), '_label -> "Grade/Tier")
<input type="submit" class="btn btn-primary" value="Save">
}
}
User Model
@Entity
@Table(name="user")
public class UserDetails extends Model
{
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
public int id;
@Column(length = 40, nullable = false, name = "first_name")
//@Constraints.Required
public String firstName;
@Column(length = 40, nullable = false, name = "last_name")
//@Constraints.Required
public String lastName;
@JoinColumn(nullable = false, name = "level_id")
@ManyToOne(fetch = FetchType.LAZY)
public GradeLevel gradeLevel;
}
Grade Model
@Entity
@Table(name="grade_level")
public class GradeLevel extends Model
{
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
public int id;
@Column(length = 40, nullable = false)
@Constraints.MinLength(2)
@Constraints.MaxLength(40)
public String name;
}
Controller
public static Result validate()
{
Form<UserDetails> submittedForm = userForm.bindFromRequest();
if(userForm.hasErrors())
{
return redirect(routes.SessionController.home());
}
else
{
UserDetails userDetails = null;
try
{
userDetails = submittedForm.get();
}
catch (IllegalStateException illegalException)
{
Logger.error("IllegalStateException",illegalException);
return redirect(routes.SessionController.home());
}
userDetails.save();
return redirect(routes.UserController.show());
}
}
Upvotes: 1
Views: 88
Reputation: 3748
There are some flaws in your code but the first big problem is here:
Form<UserDetails> submittedForm = userForm.bindFromRequest();
if(userForm.hasErrors())
You are binding the form but afterwards you check if the userForm
has errors. This must be changed to if(submittedForm.hasErrors())
- after this you will land in the true
part of your if-else
statement. This makes a huge difference!!
So you DO have an error in your form. This is most probably because of the fact that you are giving Play just a number (the value argument of your select/option) and Play expects it to be a GradeLevel
. If you print the binded form you will see something like:
Form(of=class models.UserDetails, data={lastName=bar, gradeLevel=2, firstName=foo},
Now the solution is to tell Play how to convert this '2' into a GradeLevel
.
I am aware of two options:
1) you can manually evaluate the binded form - just create your object with the provided values. You can extract the GradeLevel
with id '2' from the DB, then create a new / update existing UserDetails object with 'foo' as firstName and 'bar' as lastName, set userDetails.gradeLevel and save.
2) Have a look at
https://www.playframework.com/documentation/2.3.x/JavaForms
and especially the part on the bottom with the custom DataBinder - you can register yourself one DataBinder for the GradeLevel - just remember to do this before binding the form. Now Play will know how to handle the conversion from '2' to a GradeLevel
object and you can proceed.
Edit: please change the parameters list of your view so that you accept a Map and not a HashMap (like this Map[String,String]
). This way you don't restrict yourself only to HashMap
s. Program against interfaces.
Upvotes: 2