1

I have two selectOneMenu. I need following:

  1. On first menu change I need to populate second one and some form's fields with AJAX
  2. On second menu change I need to populate only some form's fields wit AJAX.

Populating second menu and form's fields on step 1 is perfect and right after first menu change, but there is a problem with populating form on step 2. Nothing happens when I change second menu's value. But when I returned second menu value to NoSelectionOption ajax listener invoked. It seems that AJAX listener ignores values that was added with AJAX.

Here's my code fragments:

JSF:

<h:panelGrid>
    <h:panelGrid columns="1">
        <h:panelGrid columns="1">
            <h:panelGrid columns="2">
                <h:outputText value="Получатель:" />
                <h:selectOneMenu value="#{paymentOrder.curContractor}">
                    <f:selectItem itemLabel="Выберите контрагента .." noSelectionOption="true" />
                    <f:selectItems value="#{paymentOrder.userContractors}" var="contr"
                        itemValue="#{contr.idcontractor}"
                        itemLabel="#{contr.pnamecontractor}"/>
                    <a4j:ajax event="valueChange" listener="#{paymentOrder.valueContractorChanged}" render="idINNContractor, idKPPContractor, idNameContractor, idContractorAccounts" execute="@this"/>
                </h:selectOneMenu>
            </h:panelGrid>
            <h:panelGrid columns="1">
                <h:panelGrid columns="4">
                    <h:outputText value="ИНН"/>
                    <h:inputText id="idINNContractor" value="#{paymentOrder.chosenContractor.inncontractor}"/>
                    <h:outputText value="КПП"/>
                    <h:inputText id="idKPPContractor"  value="#{paymentOrder.chosenContractor.kppcontractor}"/>
                </h:panelGrid>
                <h:panelGrid columns="2">
                    <h:outputText value="Получатель"/>
                    <h:inputTextarea id="idNameContractor" value="#{paymentOrder.chosenContractor.pnamecontractor}"/>
                </h:panelGrid>
            </h:panelGrid>
            <h:panelGrid columns="1">
                <h:panelGrid columns="2">
                    <h:outputText value="Счёт получателя:"/>
                    <h:selectOneMenu id="idContractorAccounts" value="#{paymentOrder.curContractorAccount}">
                        <f:selectItem itemLabel="Выберите счёт .."  noSelectionOption="true" />
                        <f:selectItems  value="#{paymentOrder.contractorAccounts}" var="acc"
                            itemValue="#{acc.naccountcontractor}"
                            itemLabel="#{acc.advName}"/>
                        <a4j:ajax event="valueChange" listener="#{paymentOrder.valueAccountChanged}" render="idContrAcc, idNameContrBank, idBikContrBank, idAccContrBank" execute="@this"/>
                    </h:selectOneMenu>
                </h:panelGrid>
                <h:panelGrid columns="2">
                    <h:outputText value="Сч.№"/>
                    <h:inputText id="idContrAcc" value="#{paymentOrder.curContractorAccount}"/>
                </h:panelGrid>
            </h:panelGrid>
        </h:panelGrid>      
</h:panelGrid>
<h:panelGrid columns="1">
        <h:panelGrid columns="4">   
            <h:panelGrid columns="2">
                <h:outputText value="Банк получателя"/>
                <h:inputTextarea id="idNameContrBank" value="#{paymentOrder.chosenBank.namebank}" />
            </h:panelGrid>
            <h:panelGrid columns="2">
                <h:outputText value="БИК"/>
                <h:inputText id="idBikContrBank" value="#{paymentOrder.chosenBank.bikbank}"/>
                <h:outputText value="Сч.№"/>
                <h:inputText id="idAccContrBank" value="#{paymentOrder.chosenBank.bankkorshet}"/>
            </h:panelGrid>
        </h:panelGrid>
    </h:panelGrid>
</h:panelGrid>

And my back bean fragment:

public class PaymentOrder {

    @EJB(lookup="JpaBankBean/local")
    private JpaBankBeanLocal jpaBean;
    private Paymentdocument pDocument;
    private Paymentorder pOrder;
    private Klbankrf chosenBank;

    private String curContractorAccount;
    private String curContractorBank;
    private String curContractor;
    private String err;
    private String chosenAccount;

    private Contractor chosenContractor;
    @SuppressWarnings("rawtypes")
    private Set contractorAccounts;

    @SuppressWarnings("rawtypes")
    private List contractorBanks;
    private String userName;
    private Date nowDate;
    public PaymentOrder() {
        this.nowDate = Calendar.getInstance().getTime();
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (principal instanceof UserDetails) {
              setUserName(((UserDetails)principal).getUsername());
            } else {
              setUserName(principal.toString());
            }   
        pDocument = new Paymentdocument();
        pOrder = new Paymentorder();
        chosenContractor = new Contractor();
        chosenBank = new Klbankrf();
    }
    public void valueContractorChanged()
    {
        chosenContractor = jpaBean.getContractor(Integer.valueOf(getCurContractor()));
        setContractorAccounts(jpaBean.getContractorAccounts(Integer.valueOf(getCurContractor())));
        pDocument.setReceiver(chosenContractor.getPnamecontractor());
    }
    public List getUserContractors()
    {
        return jpaBean.getUserContractors(userName);
    }
    public void valueAccountChanged()
    {
        chosenBank.setNamebank("SBER");

        //TODO chosenBank = jpaBean.getContractorBank(getCurContractorAccount());
        //TODO setChosenAccount("012345678901234567890");
    }
}

So, "SBER" appear in idNameContrBank field only if I change second menu value to somethig and then change back to NoSelectOption. It is strange to me. I use RichFaces 4, JBoss AS 6.

I've found some information at this forum, but there is no solution. How to make second menu to change something? Or is there my mistake? Any ideas?

Thanks in advance!

I've made some experiments. When I change second menu to some value populated with AJAX, page gets response like that:

<?xml version='1.0' encoding='UTF-8'?>
<partial-response>
    <changes>
        <update id="docForm:idContrAcc">
            <![CDATA[<input id="docForm:idContrAcc" type="text" name="docForm:idContrAcc" style=" width : 100%;" />]]>
        </update>
        <update id="docForm:idNameContrBank">
            <![CDATA[<textarea id="docForm:idNameContrBank" name="docForm:idNameContrBank" style=" width : 130px;"></textarea>]]>
        </update>
        <update id="docForm:idBikContrBank">
            <![CDATA[<input id="docForm:idBikContrBank" type="text" name="docForm:idBikContrBank" style=" width : 140px;" />]]>
        </update>
        <update id="docForm:idAccContrBank">
            <![CDATA[<input id="docForm:idAccContrBank" type="text" name="docForm:idAccContrBank" style=" width : 140px;" />]]>
        </update>
        <update id="javax.faces.ViewState"><![CDATA[3312710224811729695:3995303008700914422]]>
        </update>
    </changes>
</partial-response>

There are no values, but right IDs! How it can be? Why?

But if I return NoSelectionOption active then page gets response

<?xml version='1.0' encoding='UTF-8'?>
<partial-response>
    <changes>
        <update id="docForm:idContrAcc">
            <![CDATA[<input id="docForm:idContrAcc" type="text" name="docForm:idContrAcc" value="" style=" width : 100%;" />]]>
        </update>
        <update id="docForm:idNameContrBank">
            <![CDATA[<textarea id="docForm:idNameContrBank" name="docForm:idNameContrBank" style=" width : 130px;">SBER</textarea>]]>
        </update>
        <update id="docForm:idBikContrBank">
            <![CDATA[<input id="docForm:idBikContrBank" type="text" name="docForm:idBikContrBank" style=" width : 140px;" />]]>
        </update>
        <update id="docForm:idAccContrBank">
            <![CDATA[<input id="docForm:idAccContrBank" type="text" name="docForm:idAccContrBank" style=" width : 140px;" />]]>
        </update>
        <update id="javax.faces.ViewState">
            <![CDATA[3312710224811729695:3995303008700914422]]>
        </update>
    </changes>
</partial-response>

It's seems OK - values are presented! But why does it happen when NoSelectionOption is active?!

4

1 回答 1

1

我怀疑 JSF 可能会覆盖您的尝试,因为它通常会为页面上公开的所有属性调用所有设置器,并且通常在valueChangeListeners 执行后执行此操作。我从来没有见过这个<a4j:ajax />标签,但你可以试试这个<a4j:support />标签。而不是这个:

<a4j:ajax event="valueChange" listener="#{paymentOrder.valueContractorChanged}" render="idINNContractor, idKPPContractor, idNameContractor, idContractorAccounts" execute="@this"/>

尝试这个:

<a4j:support event="onchange" ajaxSingle="true" reRender="idINNContractor, idKPPContractor, idNameContractor, idContractorAccounts"/>

由于ajaxSingle="true"包含在标记中,这意味着只有 setter forcurContractor将被调用(而不是像 JSF 通常那样在页面上的所有其余部分)。然后你可以valueContractorChanged从 setter 调用(甚至只是让它成为 setter 的一部分)。

如果您<a4j:ajax />以这种方式替换所有标签,您应该会得到所需的结果。通过上面的链接查看有关标签的更多信息。

于 2011-05-31T09:15:05.857 回答