model-view-controller - Play Framework : how to repopulate form on validation-failure when using datamodel?

标签 model-view-controller playframework

我正在构建一些类似 CMS 的粗略功能(以熟悉 Play Framework)。对于这个测试用例,我构建了 2 个页面,1 个用于列出标签,1 个用于创建/编辑/保存标签。

流程是这样的(routes-file):

#list tags
GET /tags  Application.listTags 

#view/edit existing tag
GET /tag/{<(?!new$)(.+)>name} Application.showTag  

#new tag
GET /tag/new  Application.showTag   

创建/查看/编辑页面显示一个从 tagDTO 获取值的表单。 正常流程没有问题,但是当表单给出验证错误(例如:标签名称必须存在)时,我想再次显示页面,用编辑后的值重新填充表单。

为此(遵循 Play Framework 约定)我可以使用包含这些最后值的“flash”对象,但是表单已经绑定(bind)到 tagDTO(在重定向时为 null)而不是“flash”-目的。

首先是代码: 应用程序.java

.....

public static void showTag(String name) {
    TagDTO tagDTO = TagDTO.buildDTOFromModelOrNew(name);
    render(tagDTO); 
}


/**
 * Save tag and redirect to Show
 * 
 * @param name
 * @param displayname
 * @param isnew
 */
public static void saveTag(
        @Required(message="Name is required") String name,
        String displayname,
        boolean isnew) 
{
    checkAuthenticity();
    if(validation.hasErrors()) {
        params.flash(); 
        validation.keep(); 
        showTag(null);
    }

    //fetch tagDTO based on backend or create new if not exist
    TagDTO tag = TagDTO.buildDTOFromModelOrNew(name);

    // Append / Overwrite values
    tag.displayname = displayname;
    tag.name = name;

    //save result to model
    TagDTO.buildAndSaveModelFromDTO(tag);

    flash.success("Thanks for " + (isnew?"creating":"updating") + " tag " + tag.name);

    //redirect to show
    showTag(tag.name);
} 

和 ShowTag.html

    #{extends 'main.html' /}
    #{if flash.success}
        <p class="success">${flash.success}</p>
    #{/if}

    #{ifErrors}
        <p class="errors">Oops...</p>
    #{/ifErrors}

    #{form @Application.saveTag()}
        #{authenticityToken /}
        <p>
            <label for="name">Name: </label>
            <input type="text" name="name" id="name" value="${tagDTO.name}" />
            <span class="error">#{error 'name' /}</span>
        </p>
        <p>
            <label for="displayname">Displayname: </label>
            <input type="text" name="displayname" id="displayname" value="${tagDTO.displayname}" />
            <span class="error">#{error 'displayname' /}</span> 
        </p>
        <p>
            <input type="hidden" name="isnew" value="${tagDTO.isnew}" />
            <input type="submit" value="Submit your comment" />
        </p>
    #{/form}

现在我可以想出一些方法来让它工作,但没有一个是真正优雅的:

  1. 将表单绑定(bind)到 flash 对象(或 params 对象)并从 tagDTO 填充 flas/params 对象

  2. 在验证失败时,重新获取 tagDTO(不再有用,因此需要进行数据库调用)并使用闪存对象中可用的值覆盖 tagDTO 中的值,将表单绑定(bind)到 tagDTO。

  3. 类似于 2,但使用某种缓存来快速获取 tagDTO(因此不需要 db-call)

  4. 从/到 session (反)序列化 tagDTO 的一些通用机制。

简而言之,我真的不喜欢他们中的任何一个。 在这种情况下,您认为什么是最佳做法?或者 Play Framework 中是否有我缺少的任何功能?

最佳答案

这是显式渲染调用派上用场的地方。保留先前提交的表单值并将其返回(如果验证失败),如下所示,

checkAuthenticity();
if(validation.hasErrors()) {
    render("@showTag", name, displayname, isnew);
}

这将避免额外的重定向(在 Play 的情况下为 307!),如果您调用了“来自另一个操作的操作”,则会发生这种情况。

关于model-view-controller - Play Framework : how to repopulate form on validation-failure when using datamodel?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6782016/

相关文章:

c# - 如何测试这个简单的索引方法?

javascript - 无法在 JavaScript 中使用我的模型数据

scala - Playframework - Request[A] 与 RequestHeader

java - 如何将列表/字符串生成器渲染到模板

scala - 发送 FakeRequest 时如何为 akka.stream.Materializer 提供隐式值?

ios - 如何让我的 TableView 选择打开我的模态视图?

model-view-controller - 在 MVC 软件架构中放置验证逻辑的位置

asp.net-mvc - 帮助为测试响应 header 创建单元测试,特别是 Cache-Control,以确定缓存是否已禁用

scala - 为什么在 Play Framework 中使用 @Singleton 而不是 Scala 的对象?

playframework - 在 Play 2.X 的子域之间共享 session /cookie