PrimeFaces 3.0 - группа Ajax f: ajax не получает события от p: commandButton или p: commandLink - PullRequest
2 голосов
/ 10 июня 2011

Я пытаюсь интегрировать 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>

и СС:

<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.

Ответы [ 2 ]

3 голосов
/ 10 июня 2011

Таким образом, очевидно, что теги PrimeFaces <p:commandButton> и <p:commandLink> нельзя использовать взаимозаменяемо с <h:commandButton> и <h:commandLink>.Я думал, что они поддерживали базовое поведение основных тегов JSF, а затем предоставили больше вещей, специфичных для PrimeFaces, в дополнение к этому.Это не вариант.Теги PrimeFaces отличаются друг от друга и обеспечивают только некоторые характеристики основных тегов JSF с одинаковыми именами.

Так что решение моей проблемы не совсем идеальное.Теги PrimeFaces не будут участвовать в группе Ajax, используя <f:ajax> для включения группы элементов управления (как вы можете сделать с основными тегами JSF).Кроме того, командная кнопка PrimeFaces и командная ссылка не будут использовать дочерний элемент <f:ajax> или <p:ajax>.Есть два атрибута, которые он будет искать для включения поведения Ajax: «update» и «ajax».

Каждый тег должен иметь атрибут «update», который содержит разделенный пробелами список целей рендеринга Ajax, простокак атрибут 'render' <f:ajax>.Мои компоненты 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» вообще не должен предоставляться.Этот ТАК * вопрос помог мне указать верное направление.

1 голос
/ 10 июня 2011

Существуют странные проблемы, которые могут возникнуть при использовании тега <f:ajax> для компонентов Primefaces.

Попробуйте использовать тег ajax Primefaces, <p:ajax>

РЕДАКТИРОВАТЬ: я простохочу отметить, что вы можете столкнуться с проблемой с обновлением ajax <p:dataTable> из компонента в этого dataTable.Эта ошибка существовала с Primefaces 2.2.1, однако может быть исправлена ​​в 3.0.

...