PrimeFaces 3.0 - f:ajax Ajax Group没有从p:commandButton或p:commandLink接收事件

时间:2011-06-10 15:58:02

标签: java ajax jsf-2 facelets primefaces

我正在尝试将PrimeFaces 3.0集成到我的JSF 2.0项目中。我创建了一些示例代码,尝试在每行的列中使用删除按钮/链接获取PrimeFaces <p:dataTable>。我希望删除操作触发表的Ajax刷新(我当前的代码使用@form触发封闭表单的渲染)。

我的问题是,PrimeFaces组件似乎没有触发核心JSF <f:ajax>标记可以处理的事件。我使用<f:ajax>作为Ajax组,其中包含<p:dataTable>以及另一个命令按钮。

如果我纯粹使用核心JSF元素(<h:dataTable><h:commandButton>等)实现这一点,那么一切都按预期工作。请原谅丑陋的输出,但我不会为我的示例代码浪费时间在CSS样式上。

Ugly but properly functioning core JSF implementation

以下是核心JSF实施页面的代码:

<h:form id="dataTableForm">
    <f:ajax 
            listener="#{dataTableTestBean.processAjaxBehavior}"
            event="action" 
            render="@form :messages :ajaxRenderTargetsInTemplate">
        <h:panelGroup id="dataTablePanelGroup">
            <h:commandLink
                id="commandLinkAddRow"
                value="Add Sample Row"
                actionListener="#{dataTableTestBean.handleAddDataTableRow}" />
            <h:commandButton
                id="commandButtonAddRow"
                value="Add Sample Row"
                actionListener="#{dataTableTestBean.handleAddDataTableRow}" />
            <sandbox:dataTableCC
                id="dataTableCC"
                valueList="#{dataTableTestBean.dataTableList}" />
        </h:panelGroup>
    </f:ajax>
    <h:panelGroup rendered="#{empty dataTableTestBean.dataTableList}">
        <h3>No Records To Display</h3>
    </h:panelGroup>
    <h:commandButton
        id="commandButtonBackToStartPage" 
        value="#{bundle.backToStartPage}"
        action="start"
        immediate="true" />
</h:form>

以下是核心JSF实施CC的代码:

<composite:implementation>
    <h:dataTable
            id="theDataTable"
            rendered="#{not empty cc.attrs.valueList}"
            value="#{cc.attrs.valueList}"
            var="row"
            emptyMessage="#{bundle.dataTableEmptyMessage}">
        <f:facet name="header">#{bundle.dataTableHeader}</f:facet>
        <h:column id="columnDeleteButton">
            <h:commandLink
                    id="commandLinkDelete"
                    value="Delete"
                    action="#{dataTableTestBean.actionDeleteDataTableRow(row)}" />
        </h:column>
        <h:column>
            <h:commandButton
                    alt="#{bundle.delete}"
                    image="#{resource['images/onebit_33_24x24.gif']}"
                    action="#{dataTableTestBean.actionDeleteDataTableRow(row)}" />
        </h:column>
        <h:column sortBy="#{row.name}">
            <f:facet name="header">
                #{bundle.columnHeaderName}
            </f:facet>
            <h:outputText value="#{row.name}" />  
        </h:column>
        <h:column sortBy="#{row.rank}">
            <f:facet name="header">
                #{bundle.columnHeaderRank}
            </f:facet>
            <h:outputText value="#{row.rank}" />  
            <f:facet name="footer">
                #{bundle.columnFooterRank}
            </f:facet>
        </h:column>
        <h:column sortBy="#{row.serialNumber}">
            <f:facet name="header">
                #{bundle.columnHeaderSerialNumber}
            </f:facet>
            <h:outputText value="#{row.serialNumber}" />  
            <f:facet name="footer">
                #{bundle.columnFooterSerialNumber}
            </f:facet>
        </h:column>
        <f:facet name="footer">#{bundle.dataTableFooter}</f:facet>
    </h:dataTable>
</composite:implementation>

核心JSF实现将很好地触发Ajax事件并执行部分页面渲染,其中一部分是<h:messages>的渲染,确认事件已成功处理。

当我用<h:dataTable>替换<p:dataTable>时,没问题。但是,如果我将<h:commandButton><h:commandLink>替换为<p:commandButton><p:commandLink>,则Ajax事件不会进入<f:ajax> Ajax Group元素。记录删除和插入操作确实在服务器上发生,但页面永远不会刷新。我会向用户显示没有任何反应。如果单击浏览器“刷新”按钮,您将看到操作确实发生了。如果单击核心JSF命令按钮或命令链接,一切正常。 PrimesFaces表呈现,甚至PrimeFaces“咆哮”弹出窗口也按预期显示。

以下是有问题的PrimeFaces实施的屏幕截图。再次,请原谅按钮和链接的丑陋。

PrimeFaces implementation that has Ajax event problems

首先,页面:

<p:growl id="growl" showSummary="false" showDetail="true" />
<h:form id="dataTableForm" styleClass="ui-widget">
    <f:ajax
        listener="#{dataTableTestBean.processAjaxBehavior}"
        event="action"
        render="@form :growl :ajaxRenderTargetsInTemplate">
        <h:panelGroup id="dataTablePanelGroup">
            <p:commandLink
                id="pfCommandLinkAddRow"
                value="Add Sample Row (pf)"
                ajax="true"
                actionListener="#{dataTableTestBean.handleAddDataTableRow}" />
            <p:commandButton
                id="pfCommandButtonAddRow"
                value="Add Sample Row (pf)"
                ajax="true"
                actionListener="#{dataTableTestBean.handleAddDataTableRow}" />
            <h:commandLink
                id="hCommandLinkAddRow"
                value="Add Sample Row (h)"
                actionListener="#{dataTableTestBean.handleAddDataTableRow}" />
            <h:commandButton
                id="hCommandButtonAddRow"
                value="Add Sample Row (h)"
                actionListener="#{dataTableTestBean.handleAddDataTableRow}" />
            <sandbox:primeFacesDataTableCC
                id="dataTableCC"
                valueList="#{dataTableTestBean.dataTableList}" />
        </h:panelGroup>
    </f:ajax>
    <h:panelGroup rendered="#{empty dataTableTestBean.dataTableList}">
        <h3>No Records To Display</h3>
    </h:panelGroup>
    <h:commandButton
        id="commandButtonBackToStartPage" 
        value="#{bundle.backToStartPage}"
        action="start"
        immediate="true" />
</h:form>

和CC:

<composite:implementation>
    <p:dataTable
            id="theDataTable"
            rendered="#{not empty cc.attrs.valueList}"
            value="#{cc.attrs.valueList}"
            var="row"
            emptyMessage="#{bundle.dataTableEmptyMessage}">
        <f:facet name="header">#{bundle.dataTableHeader}</f:facet>
        <p:column id="columnpclDelete">
            <p:commandLink
                    id="pclDelete"
                    value="Delete (pf)"
                    action="#{dataTableTestBean.actionDeleteDataTableRow(row)}" />
        </p:column>
        <p:column id="columnpcbDeleteIconOnly">
            <p:commandButton
                    id="pcbDeleteIconOnly"
                    ajax="true"
                    global="true"
                    alt="#{bundle.delete}"
                    image="ui-icon ui-icon-trash"
                    action="#{dataTableTestBean.actionDeleteDataTableRow(row)}" />
        </p:column>
        <p:column id="columnhclDelete">
            <h:commandLink
                    id="hclDelete"
                    value="Delete (h)"
                    action="#{dataTableTestBean.actionDeleteDataTableRow(row)}" />
        </p:column>
        <p:column id="columnhcbDeleteWithImage">
            <h:commandButton
                    id="hcbDeleteWithImage"
                    alt="#{bundle.delete}"
                    image="#{resource['images/onebit_33_24x24.gif']}"
                    action="#{dataTableTestBean.actionDeleteDataTableRow(row)}" />
        </p:column>
        <p:column id="columnName" sortBy="#{row.name}">
            <f:facet name="header">
                #{bundle.columnHeaderName}
            </f:facet>
            <h:outputText value="#{row.name}" />  
        </p:column>
        <p:column id="columnRank" sortBy="#{row.rank}">
            <f:facet name="header">
                #{bundle.columnHeaderRank}
            </f:facet>
            <h:outputText value="#{row.rank}" />  
            <f:facet name="footer">
                #{bundle.columnFooterRank}
            </f:facet>
        </p:column>
        <p:column id="serialNumber" sortBy="#{row.serialNumber}">
            <f:facet name="header">
                #{bundle.columnHeaderSerialNumber}
            </f:facet>
            <h:outputText value="#{row.serialNumber}" />  
            <f:facet name="footer">
                #{bundle.columnFooterSerialNumber}
            </f:facet>
        </p:column>
        <f:facet name="footer">#{bundle.dataTableFooter}</f:facet>
    </p:dataTable>
</composite:implementation>

我哪里出错了?除PrimeFaces组件的Ajax事件外,一切正常。

2 个答案:

答案 0 :(得分:3)

显然,PrimeFaces <p:commandButton><p:commandLink>代码无法与<h:commandButton><h:commandLink>互换使用。我认为他们支持核心JSF标记的基本行为,然后提供更多PrimeFaces特定的东西。不是这种情况。 PrimeFaces标签是不同的,只提供同名核心JSF标签的一些行为。

所以解决我的问题并不是很理想。 PrimeFaces标记不会使用<f:ajax>来包含一组控件(正如您可以使用核心JSF标记一样)参与Ajax组。此外,PrimeFaces命令按钮和命令链接不会使用<f:ajax><p:ajax>子项。它将寻找启用Ajax行为的两个属性:'update'和'ajax'。

每个标记必须具有'update'属性,该属性包含以空格分隔的Ajax渲染目标列表,就像<f:ajax>的'render'属性一样。我的PrimeFaces组件位于复合组件内部,因此我必须通过CC接口属性传递渲染目标列表。

CC中的我的命令按钮现在看起来像这样:

<p:commandButton
    id="pCommandButtonDeleteIconOnly"
    alt="#{bundle.delete}"
    image="ui-icon ui-icon-trash"
    ajax="true"
    update="#{cc.attrs.ajaxRenderTargets}"
    action="#{dataTableTestBean.actionDeleteDataTableRow(row)}" />

如果我不希望命令按钮作为Ajax调用执行,那么显然'ajax'属性应设置为“false”,并且根本不应提供'update'属性。这个SO question帮助我指明了正确的方向。

答案 1 :(得分:1)

如果您对Primefaces组件使用<f:ajax>标记,则会出现一些奇怪的问题。

尝试使用Primefaces ajax标记<p:ajax>

编辑:我只是想指出,可能在数据表的 组件中遇到<p:dataTable>的ajax刷新问题。这个错误从Primefaces 2.2.1开始存在,但可能在3.0中修复。