Приложение JSF, действия не работают, если ранее было вызвано другое действие - PullRequest
1 голос
/ 25 июня 2011

Я изучаю Java EE 6 и JSF 2.0 на JBoss6 и создал очень простое одностраничное приложение "Todo", которое работает, но с очень странной ошибкой. Протестировано в Safari 5.0.5 и Firefox 5.

Есть два действия, которые вы можете сделать (добавить задачу и проверить / снять галочку с задач). Это все работает, но не в первый раз, когда действие выполняется после выполнения другого действия.

И пример использования может выглядеть так:

  1. попробуйте добавить задачу = успех
  2. попробуйте добавить задачу = успех
  3. попытаться проверить todo = fail
  4. попытаться проверить задачу = успех
  5. попробуйте добавить todo = fail
  6. попробуйте добавить задачу = успех
  7. попытаться проверить todo = fail

Приложение имеет следующие основные файлы (плюс другие фрагменты):

  • entity / Todo.java <- JPA entity </li>
  • Manager / TodoManager.java <- EJB для обработки сущностей Todo, @ Stateless </li>
  • controllers / TodoController.java <- управляемый компонент для страницы, @SessionScoped </li>
  • todos.xhtml <- страница JSF </li>

Без лица-config.xml

Форма для добавления задачи выглядит следующим образом:

<h:panelGroup id="projects">
   <h:message for="newtitle" />
   <h:form id="newtodo">
    <h:panelGrid columns="5">
            <h:outputText value="New Todo: "/>
            <h:inputText id="newtitle" value="#{todoController.todo.title}" />
            <h:outputText value="Due: "/>
            <h:inputText id="newDueDate" value="#{todoController.todo.dueDate}">
                <f:convertDateTime pattern="dd/mm/yyyy"/>
            </h:inputText>
            <h:commandButton action="#{todoController.addTodo}" value="add">
                <f:ajax execute="@form" render=":projects"/>
            </h:commandButton>

Форма для проверки / снятия статуса todo "done" выглядит следующим образом:

<h:form>
    <h:dataTable id="todolist" var="t" value="#{todoController.todolist}">
        <h:column>
            <h:selectBooleanCheckbox id="rowCheckbox" value="#{t.done}" >
                <f:ajax event="click" listener="#{todoController.updateDone(t)}" render=":projects"/>
            </h:selectBooleanCheckbox>
        </h:column>

TodoController выглядит так:

@ManagedBean(name="todoController")
@SessionScoped
public class TodoController 
{
    @EJB
    private TodoManager todoManager;
    private Todo todo = new Todo();
    private ArrayList<Todo> todolist = new ArrayList<Todo>();

    public String addTodo()
    {
        todo.setDone(false);
        todo.setUser(this.getLoggedInUser());
        todoManager.addTodo(todo);
        todo = null;
        return "todos.xhtml";
    }

    public String updateDone(Todo t)
    {
        t.setDone(!t.getDone());
        todoManager.updateTodo(t);
        return "todos.xhtml";
    }

Я добавил сообщения регистрации в addTodo () и updateDone (Todo t), чтобы проверить, когда их вызывают. Когда действия "не работают", на самом деле, кажется, их вообще не вызывают. : - (

1 Ответ

1 голос
/ 25 июня 2011

Это произойдет, если у вас есть 2 формы, вторая форма которых переопределяется путем добавления первой формы. Таким образом, состояние представления JSF второй формы будет полностью потеряно (вы можете определить его самостоятельно по отсутствию скрытого поля ввода с именем javax.faces.ViewState в ответе Ajax). Отправка второй формы после повторной визуализации путем отправки первой формы визуально не будет иметь никакого эффекта. Без состояния просмотра JSF не будет обрабатывать отправку формы. Только новая форма (с надлежащим состоянием просмотра!) Вернется на место, и, следовательно, вторая отправка работает.

Вам необходимо точно настроить атрибут render таким образом, чтобы перерисовывалось только содержимое второй формы, а не вся форма.

1007 * Е.Г. *

<h:form id="form1">
    <h:panelGroup id="content">
        ...
        <h:commandButton value="Submit">
            <f:ajax execute="@form" render="@form :form2:content" />
        </h:commandButton>
    </h:panelGroup>
</h:form>
<h:form id="form2">
    <h:panelGroup id="content">
        ...
        <h:commandButton value="Submit">
            <f:ajax execute="@form" render="@form :form1:content" />
        </h:commandButton>
    </h:panelGroup>
</h:form>

В вашем конкретном случае, присвойте <h:panelGrid> первой формы и <h:dataTable> второй формы фиксированный id и заново отрендерите только что из другой формы на.

...