【问题标题】:Commandbutton in panelgroup面板组中的命令按钮
【发布时间】:2011-09-16 07:01:29
【问题描述】:

我有一个带有 GET 参数的页面,例如:/manageSquare.xhtml?squareName=foobar。此页面有一个请求范围的支持 bean。为了正确初始化支持 bean,该 bean 包含一个 initialize 方法,该方法将被调用,因为该页面包含一个带有 <f:viewParam><f:event type="preRenderView ...><f:metadata>。有时方块不存在,并且会显示一些特殊的错误信息。因此有一个<h:panelGroup rendered="#{squareBean.squareExist}"> 元素。

现在 - 问题是如果我在这样的 <h:panelGroup> 中有一个 <h:commandButton> 元素,那么每当提交表单时,只会发生导航但永远不会调用操作方法!这怎么可能?

这是一些概念性代码(归结)

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:h="http://java.sun.com/jsf/html"
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:fn="http://java.sun.com/jsp/jstl/functions"
            template="../template.xhtml">
<ui:param name="title" value="Square"/>
<f:metadata>
    <f:viewParam name="squareName" value="#{manageSquareBean.squareName}"/>
    <f:event type="preRenderView" listener="#{manageSquareBean.initialize}"/>
</f:metadata>
<ui:define name="content">
    <h1>Manage square <h:outputText escape="true" value="#{manageSquareBean.squareName}"/></h1>
    <h:panelGroup rendered="#{!manageSquareBean.squareExists}">
        <span class="error">Square does not exist</span>
    </h:panelGroup>
    <h:panelGroup rendered="#{manageSquareBean.squareExists}">
        <h:form>           
            <h:commandButton action="#{manageSquareBean.addUsersToSquare}" value="Add users">
                <f:param name="squareName" value="#{manageSquareBean.squareName}"/>
            </h:commandButton>
         </h:form>
    </h:panelGroup>
</ui:define>
</ui:composition>

这是一个 managedBean:

@RequestScoped
@ManagedBean
public class ManageSquareBean
{
    private String squareName;

    private boolean squareExists;
    private List<String> usersToAdd;

    public void initialize()
    {
        // Find out if squareName exists
        squareExists = squareExists(squareName);
    }

    public String addUsersToSquare()
    {
        // Do something
    }

    // Getters and setters
}

我真的不明白为什么会这样。删除&lt;panelGroup&gt;,一切都很好。此外,当按下 commandButton 时,似乎 squareName 参数没有向前发送。

Here 是一个有同样问题的人。他使用 JSTL 而不是 &lt;panelGroup&gt; 解决了这个问题,但是 JSTL 将在调用 initialize 方法之前的构建时间运行。

请帮忙,我在这个问题上用了很多小时。

【问题讨论】:

    标签: jsf-2


    【解决方案1】:

    输入和命令组件的rendered 属性及其所有父组件在表单提交的应用请求值阶段重新评估。由于您的 bean 是请求范围的,因此在提交时会创建一个全新的 bean,因此 rendered 属性的条件默认为 false,因此该按钮永远不会呈现,因此也永远不会被调用。

    您的 bean 需要放在视图范围内。

    @ManagedBean
    @ViewScoped
    public class ManageSquareBean
    

    这样,只要您与同一个视图交互,bean(以及它所拥有的所有布尔条件)就会一直存在。

    另见:

    【讨论】:

    • 嗯。这确实有效。我不懂为什么。根据你的解释,一切都重新评估。我已经使用调试器检查了 squareExists 设置为 true,无论是在呈现表单时还是在发布表单时。因此,我真的不明白为什么会这样。你是说当请求值被应用时,我的初始化函数没有在 RequestScoped bean 中被调用?
    • 在调用动作阶段调用初始化函数。在那之前,布尔值仍然是假的,因为它是全新 bean 实例的默认值。应用请求值阶段(当 JSF 重新检查该条件以收集提交的值和按下的按钮/链接时)运行 before 调用操作阶段。
    【解决方案2】:

    我确定 panelGroup 不是问题所在。

    我有 2 条建议给你:

    1) 检查您是否继承了表单。有时会发生通过模板方法将表单元素驻留在另一个表单中的情况。 JSF 无法正确处理此问题

    2) 或许您需要使用定义标签和名称元数据来包装 f:metadata。

    http://javaserverfaces.java.net/nonav/docs/2.0/pdldocs/facelets/f/metadata.html

    <ui:define name="metadata">
    <f:metadata>
        <f:viewParam name="squareName" value="#{manageSquareBean.squareName}"/>
        <f:event type="preRenderView" listener="#{manageSquareBean.initialize}"/>
    </f:metadata>
    </ui:define>
    

    【讨论】:

    • 1) 没有嵌套表单。然而,viewstate id 被定义了多次——这可能是个问题吗?有关完整的 html,请参阅 pastebin。 2)试过了,但没有改变任何东西。无论哪种方式都调用侦听器。
    • 另外,如果我在示例中删除 PanelGroup,它怎么会正常工作?我真的认为这是问题所在 - 但我不知道我是正确的还是你暗示的其他问题。
    • ViewState 不是问题。我刚刚查看了我们的项目,发现了相同的行为。
    • 您可以尝试将表单移出panelGroup。这只是一个猜测,但也许渲染和表单存在问题。通常这应该可以工作,但谁知道呢。对了,你有哪个jsf版本的?
    • 好点,但实际上不适用于 OP 的特定问题。嵌套表单不是原因,因为它在删除面板组时起作用。元数据声明非常好。它只需要是 f:view 的子级。
    猜你喜欢
    • 2014-07-28
    • 1970-01-01
    • 1970-01-01
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 1970-01-01
    相关资源
    最近更新 更多