如何在Play Framework 2(Java)中处理表单中的全局错误

时间:2015-05-20 16:31:05

标签: java playframework playframework-2.3

在Play Framework 2(Java)中处理表单中的错误时,我想提供一条警告用户出错的全面错误消息,例如: " 表格X未更新"。一种方法是,除了每个表单字段的错误之外,还要创建一个全局错误,然后在每个模板上显示:

控制器:

if(form.hasErrors()) {
    form.reject("Form X not updated."); // This creates a global error
}

模板:

@if(form.hasGlobalErrors) {
    @someFunctionToPresentErrors(from.globalError.message))
}

但是,将这段相同的代码添加到包含表单的每个模板都违反了DRY原则。

到目前为止,我最好的解决方案是将错误消息添加到Http.Context,然后拦截每个模板调用的主模板中的错误消息:

控制器:

Http.Context.current().args.put("error", "Form X not updated.");

主要模板:

@if(Http.Context.current().args.containsKey("error")){
    @someFunctionToPresentErrors(
        Http.Context.current().args.get("error").asInstanceOf[String])
}

这样做更好,因为它允许我将错误演示文稿内容保存在一个地方,但感觉就像滥用Http.Context一样。请注意,flash(...)也可用于隐式传递变量并提供与Http.Context相同的效果,但在调用badRequest(...)时不允许这样做,因为闪存只应用于重定向。无论如何,我认为应该有更好的方法来使用Play Framework提供的表单机制。

这是最好的做法吗?

1 个答案:

答案 0 :(得分:4)

我认为你在这种情况下高估了 DRY违规 - 实际上我意识到即使全球错误也不是全球性的 - 实际上每种形式都有它&#39 ;自己的背景。无论如何,为了加快工作速度,您可以使用template tagsFlash scope

首先添加两个通用公共方法,即Application控制器

public static void flashGlobalError() {
    flashGlobalError("Oppps... error occurred and I don't know the reason ;(");
}

public static void flashGlobalError(String msg) {
    flash("globalError", msg);
}

然后创建无参数tag template,即views/tags/globalErrorByFlash.scala.html

@if(flash.get("globalError")) {
    <div style="background: red">
        <h4>Error!</h4>
        @flash.get("globalError")
    </div>
}

并将其包含在您的main模板中(或仅限于所选视图中):

<body>
    @tags.globalErrorByFlash()
    @content
</body>

因此,每当您想要显示此错误时,您都可以在您的操作中执行此操作:

if(form.hasErrors()) {
    Application.flashGlobalError();
    return badRequest(...);
}

if(form.hasErrors()) {
    Application.flashGlobalError("This case is quite bit different...");
    return badRequest(...);
}

这种方法的最大好处是您不需要依赖Form.form(T),因为您可以在任何地方使用它:

if (1 != 0){
    Application.flashGlobalError("Stupido! One isn't equal to Zero!");
}

最后:请记住,闪存范围中保留的任何值仅适用于一个请求,因此重定向后可能会消失。视图/模板渲染也会计算在内,因此如果您将错误重定向到新操作,请将其转发到控制器中,以便重定向视图可以看到它。