1

我正在 JBoss6 上学习 Java EE 6 和 JSF 2.0,并构建了一个非常简单的单页“Todo”应用程序,该应用程序可以运行但有一个非常奇怪的错误。在 Safari 5.0.5 和 Firefox 5 中测试。

您可以执行两个操作(添加待办事项和选中/取消选中待办事项)。这一切都有效,但不是第一次在完成不同的操作后完成一个操作。

示例用法可能如下所示:

  1. 尝试添加待办事项 = 成功
  2. 尝试添加待办事项 = 成功
  3. 尝试检查待办事项 = 失败
  4. 尝试检查待办事项 = 成功
  5. 尝试添加待办事项 = 失败
  6. 尝试添加待办事项 = 成功
  7. 尝试检查待办事项 = 失败

该应用程序具有以下基本文件(以及其他零碎):

  • 实体/Todo.java <- JPA 实体
  • manager/TodoManager.java <- 用于处理 Todo 实体的 EJB,@Stateless
  • controllers/TodoController.java <- 页面的托管 bean,@SessionScoped
  • todos.xhtml <- JSF 页面

没有面孔-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>

检查/取消选中待办事项“完成”状态的表单如下所示:

<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) 以验证它们何时被调用。当动作“不起作用”时,它们实际上似乎根本没有被调用。:-(

4

1 回答 1

1

当您有 2 种形式时会发生这种情况,其中第二种形式是通过合并第一种形式重新呈现的。这样,第二个表单的 JSF 视图状态将完全丢失(您可以通过javax.faces.ViewState在 Ajax 响应中缺少带有名称的隐藏输入字段来自行确定)。在通过第一个表单的提交重新呈现后提交第二个表单将在视觉上没有效果。如果没有视图状态,JSF 将不会处理表单的提交。只有一个新表单(具有正确的视图状态!)会恢复原状,因此第二次提交有效。

您需要对render属性进行微调,以便仅重新呈现第二个表单的内容而不是整个表单本身。

例如

<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并从另一个形式开始重新渲染。

于 2011-06-25T14:09:51.043 回答