如何使用AJAX创建两个相互依赖的JSF selectOneMenu?

时间:2011-05-31 05:53:57

标签: java ajax jsf richfaces selectonemenu

我有两个selectOneMenu。我需要关注:

  1. 在第一个菜单更改时,我需要使用AJAX
  2. 填充第二个和某个表单的字段
  3. 在第二个菜单更改时,我需要仅使用AJAX填充某些表单的字段。
  4. 在第一个菜单更改后,在第1步中填充第二个菜单和表单的字段是完美的,但是在第2步填充表单时出现问题。 当我改变第二个菜单的值时没有任何反应。但是当我将第二个菜单值返回给NoSelectionOption时,调用了ajax监听器。看来AJAX监听器忽略了用AJAX添加的值。

    这是我的代码片段:

    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>
    

    我的背豆片段:

    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");
        }
    }
    

    因此,只有当我将第二个菜单值更改为somethig然后更改回NoSelectOption时,“SBER”才会出现在idNameContrBank字段中。这对我来说很奇怪。 我使用RichFaces 4,JBoss AS 6。

    我在forum找到了一些信息,但没有解决方法。 如何让第二个菜单改变一些东西?还是我的错误?有什么想法吗?

    提前致谢!

    我做了一些实验。 当我将第二个菜单更改为使用AJAX填充的某个值时,页面会得到如下响应:

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

    没有值,但是正确的ID!它怎么样?为什么呢?

    但是如果我返回NoSelectionOption,那么页面会得到响应

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

    似乎没问题 - 提出了价值观!但是为什么在NoSelectionOption处于活动状态时会发生这种情况?!

1 个答案:

答案 0 :(得分:1)

我怀疑JSF可能会覆盖您的尝试,因为它通常调用页面上公开的所有属性的所有setter,并且通常在执行valueChangeListener之后执行此操作。我从未见过<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"包含在标记中,这意味着只会调用curContractor的setter(而不是像JSF通常那样在页面上的其余部分)。然后你可以从setter中调用valueContractorChanged(或者甚至让它成为setter的一部分)。

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

相关问题