игровой фреймворк: как заново заполнить форму при валидации-сбое при использовании модели данных? - PullRequest
3 голосов
/ 22 июля 2011

Я создаю некоторые грубые CMS-подобные функциональные возможности (чтобы познакомиться с Play Framework). Для этого теста я построил 2 страницы, 1 для перечисления тегов и 1 для создания / редактирования / сохранения тегов.

Поток такой (маршрут-файл):

#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' -объект, который содержит эти последние значения, но форма уже связана с tagDTO (который равен null при перенаправлении) вместо 'flash' - объект.

Сначала код: Application.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);
} 

And 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. привязать форму к flash-объекту (или params-объекту) и заполнить объект flash / params из тега DTO

  2. в случае сбоя проверки, повторно запустите tagDTO (больше не используется, поэтому необходим вызов DB) и перезапишите значения в tagDTO значениями, доступными во flash-объекте, свяжите форму с tagDTO.

  3. как 2, но с использованием некоторого кеша для быстрого извлечения tagDTO (поэтому нет необходимости в db-call)

  4. Какой-то общий механизм (де) сериализации tagDTO из / в сеанс.

Короче, мне не нравится ни один из них на самом деле. Что вы считаете лучшей практикой в ​​этой ситуации? Или в Play Framework есть какие-то функции, которые мне не хватает?

Ответы [ 2 ]

2 голосов
/ 22 июля 2011

Здесь явные вызовы рендеринга пригодятся.Сохраните значения формы из предыдущей отправки и верните ее (если проверка не удалась) следующим образом:

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

Это позволит избежать дополнительного перенаправления (307 в случае Play!), Которое могло бы произойти, если бы вы вызвали«действие из другого действия».

0 голосов
/ 22 июля 2011

Рендеринг формы снова и избежать перенаправления является решением. Я думаю, что все в порядке, если пользователь нажмет F5, он снова получит ошибку. Но я думаю, что вы должны создать кнопку перезагрузки / отмены, чтобы пользователь мог отклонить всю информацию.

Чтобы всегда иметь правильный URL-адрес, вы можете сделать следующее в route.conf:

GET  /tag/create     TagController.create
POST /tag/create     TagController.insert

Недостатком флеш-решения является то, что ваш cookie может стать очень большим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...