我是Play框架的新手,我试图保存由管理员查看的用户信息。我正在使用表单助手渲染视图。视图中的字段之一是下拉框,该框允许用户选择成绩级别,该级别具有成绩ID的值,并且显示文本具有成绩名称。在我的用户模型中,我具有作为GradeLevel的字段,该字段引用了GradeLevel模型。从下拉框中选择相应的成绩ID时,我不知道如何设置GradeLevel对象。现在,它引发了非法状态异常:提交表单时没有值。

在下面的代码段中给出。

视图

@(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">
    }
}


用户模型

@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;
}


等级模型

@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;
}


控制者

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());
    }
}

最佳答案

您的代码中存在一些缺陷,但第一个大问题在这里:

Form<UserDetails> submittedForm = userForm.bindFromRequest();

if(userForm.hasErrors())


您正在绑定表单,但是之后您检查userForm是否有错误。必须将其更改为if(submittedForm.hasErrors())-之后,您将进入true语句的if-else部分。这有很大的不同!

因此,您的表单确实有错误。这很可能是因为您只给Play提供了一个数字(选择/选项的value参数),而Play期望它是一个GradeLevel。如果您打印绑定的表格,您将看到类似以下内容的内容:

Form(of=class models.UserDetails, data={lastName=bar, gradeLevel=2, firstName=foo},


现在的解决方案是告诉Play如何将“ 2”转换为GradeLevel

我知道两个选择:

1)您可以手动评估绑定表单-只需使用提供的值创建对象即可。您可以从数据库中提取ID为'2'的GradeLevel,然后创建一个新的/更新现有的UserDetails对象,并将'foo'作为firstName,将'bar'作为lastName,设置userDetails.gradeLevel并保存。

2)看看
https://www.playframework.com/documentation/2.3.x/JavaForms
尤其是底部带有自定义DataBinder的部分-您可以为自己的GradeLevel注册一个DataBinder-只需记住在绑定表单之前进行此操作即可。现在,Play将知道如何处理从'2'到GradeLevel对象的转换,您可以继续进行。

编辑:请更改视图的参数列表,以便您接受Map而不是HashMap(例如Map[String,String])。这样,您就不会只限于HashMap。针对接口进行编程。

10-02 10:03