我正在尝试将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样式上。
以下是核心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实施的屏幕截图。再次,请原谅按钮和链接的丑陋。
首先,页面:
<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事件外,一切正常。
答案 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中修复。