Я пытаюсь интегрировать 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>
и СС:
<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>
Где я ошибся? Все работает правильно, за исключением событий Ajax от компонентов PrimeFaces.