【问题标题】:How to set object reference in model when respective object id is selected from drop down box从下拉框中选择相应的对象 ID 时如何在模型中设置对象引用
【发布时间】:2014-09-22 17:27:39
【问题描述】:

我是 Play 框架的新手,我正在尝试保存管理员在视图中输入的用户信息。我正在使用表单助手渲染视图。视图中的一个字段是下拉框,它允许用户选择等级级别,其值为等级 id,显示文本具有等级名称。在我的用户模型中,我将字段作为 GradeLevel 引用 GradeLevel 模型。从下拉框中选择相应的等级 ID 时,我不知道如何设置 GradeLevel 对象。现在它抛出非法状态异常:提交表单时没有值。

给出下面的代码sn-ps。

查看

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

【问题讨论】:

    标签: java playframework playframework-2.0


    【解决方案1】:

    你的代码有一些缺陷,但第一个大问题在这里:

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

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

    所以您的表单确实有错误。这很可能是因为您只给 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])。这样您就不会仅限于HashMaps。针对接口编程。

    【讨论】:

    • 感谢您的意见。现在我选择了你的第二个选项Custom Data binder,它可以工作。
    猜你喜欢
    • 2020-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-19
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多