Событие Ajax в dataTable, которое повторно отображается другим событием ajax, не выполняется - PullRequest
1 голос
/ 03 февраля 2012

Я создаю приложение для выставления счета. Когда пользователь выбирает клиента, службы, связанные с клиентом, повторно отображаются в dataTable посредством события ajax. Но событие ajax для selectOneMenu в dataTable не запускается.

Это форма, которая позволяет пользователю выбрать клиента:

<h:form>
    <h:selectOneMenu id="clientSelect" value="#{invoiceBean.client}">
        <f:ajax execute="clientSelect" listener="#{invoiceServiceListener.processClientValueChange}" render=":test :invoiceData"/>
        <f:selectItems value="#{invoiceBean.clientOptions}"/>
    </h:selectOneMenu>
</h:form>

Это вызовет событие ajax, которое заполняет массив служб в invoiceBean и повторно отображает таблицу данных, которая отображает службы в другом selectOneMenu в таблице данных. Эта часть работает правильно.

Это таблица данных, которая отображается после выбора клиента с помощью приведенной выше формы:

<h:panelGroup id="test">
    <h:dataTable id="invoiceData" value="#{attributes.priceAttributes}" var="loop">
        <h:column>
            <ui:param name="service" value="service#{loop}" /> 
            <ui:param name="description" value="description#{loop}" />
            <ui:param name="price" value="price#{loop}" />
            <h:form id="invoiceSelectMenu">
                <h:selectOneMenu id="selectMenu" value="#{invoiceBean[service]}">
                    <f:ajax event="change" execute="selectMenu" listener="#{invoiceServiceListener.procesServiceValueChange}" render="@form" />
                    <f:attribute name="row" value="#{loop}" />
                    <f:selectItems value="#{invoiceBean.services}" />
                </h:selectOneMenu>
                <h:inputText id="description" value="#{invoiceBean[description]}" />
                <h:inputText id="price" value="#{invoiceBean[price]}" />
                <h:outputText value="#{loop}" />
            </h:form>
        </h:column>
    </h:dataTable>  
</h:panelGroup>

selectOneMenu заполнен правильно. Однако событие ajax в этом меню выбора одного не работает после того, как оно было перерисовано первой формой. Но если я вручную заполняю массив services без отправки первой формы, то это событие ajax выполняется нормально. Кстати, это ajax-событие также устанавливает значение для полей описания и ввода цены, которые должны быть повторно обработаны при возникновении события. InvoiceBean является областью запроса.

1 Ответ

2 голосов
/ 07 февраля 2012

Это будет сложно. Из-за спецификации JSF 790 , всякий раз, когда вы повторно визуализируете некоторый контент, содержащий другой <h:form>, используя <f:ajax>, его состояние просмотра будет потеряно. Чтобы решить эту проблему, вам нужно будет ссылаться на полный идентификатор клиента другой <h:form> внутри <f:ajax> вместо некоторого содержащего компонента. Но у вас есть несколько форм внутри <h:dataTable>, на которые нельзя ссылаться по абсолютному идентификатору клиента.

Вам нужно изменить код, чтобы поставить <h:form> за пределы <h:dataTable> и изменить <f:ajax> на execute только необходимые компоненты.

<h:form id="invoiceDataForm">
    <h:dataTable id="invoiceData" value="#{attributes.priceAttributes}" var="loop">
        <h:column>
            <ui:param name="service" value="service#{loop}" /> 
            <ui:param name="description" value="description#{loop}" />
            <ui:param name="price" value="price#{loop}" />
            <h:selectOneMenu id="selectMenu" value="#{invoiceBean[service]}">
                <f:ajax execute="selectMenu,description,price" listener="#{invoiceServiceListener.procesServiceValueChange}" render="@form" />
                <f:attribute name="row" value="#{loop}" />
                <f:selectItems value="#{invoiceBean.services}" />
            </h:selectOneMenu>
            <h:inputText id="description" value="#{invoiceBean[description]}" />
            <h:inputText id="price" value="#{invoiceBean[price]}" />
            <h:outputText value="#{loop}" />
        </h:column>
    </h:dataTable>
</h:panelGroup>

, а затем ссылаться на него в первой форме следующим образом:

<f:ajax execute="clientSelect" listener="#{invoiceServiceListener.processClientValueChange}" render=":invoiceDataForm" />

Обратите внимание, что некоторые библиотеки компонентов, такие как PrimeFaces, уже обошли / решили эту проблему в специальном движке ajax библиотеки компонентов. Поэтому, если может случиться так, что вы уже используете PrimeFaces, вы также можете заменить <f:ajax> первой формы на <p:ajax>.


Не связанный с конкретной проблемой, <f:attribute name="row" value="#{loop}" /> может не выполнять то, что вы ожидаете. Он установит null, потому что теги <f:xxx> выполняются во время построения представления, а не во время отображения времени рендеринга. #{loop} недоступен во время просмотра. Но это тема для другого вопроса:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...