How to loop and get the values from all the compon

2019-08-27 20:38发布

问题:

I have a XPage with a repeat control getting its values from a viewScope vector.

<xp:repeat id="repeat1" rows="100" indexVar="i" value="#{javascript:viewScope.v1}"
</xp:repeat>

The fields are binded to the vector like this

<xp:inputText value="#{viewScope.v3[i]}" id="qty" style="width:80px"</xp:inputText>

I have managed to get the update correctly by using the onChange event on the input boxes. something like this.

<xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="qty">
                                            <xp:this.action><![CDATA[#{javascript:var v3:java.util.Vector = viewScope.v3
v3.setElementAt(getComponent("qty").getValue(),i)
viewScope.v3 = v3;

    }]]></xp:this.action>
                                        </xp:eventHandler>

The problem is that the onChange event is updating the inputfield so if user is too fast typing the entered values are lost and they need to type it again.

so I am looking for a way to loop the viewScope and set all the row values in the save button instead.

So in my save button I want to loop the values in the viewScope and put them all in a new Vector that I can write to the document fields. basically I need to get hold of the values the user enterd using getComponent("").getValue() for each row in an SSJS loop.

how can I do that.

回答1:

The values are already correctly saved if your save button performs the submit with the correct execution mode/id combo.

You don't state the reason why you initially chose to submit new values with the onchange event but the collateral problem, the one that users' new values get wiped sometimes, can be overcome by declaring the event with the refreshMode property set to norefresh. This will instruct the framework to do the submit and not destroy and recreate the input field the event is generated from. It might be just what you want, unless you want to give visual feedback for invalid values, if not performed client side with JavaScript prior the call. I can also see that you are not declaring the execMode to partial thus sending more than it's necessary to the server for evaluation. Remember to use it.

Having tha being said, this will work and respects your initial idea (don't mind the different names and console.log line I added just for testing purposes):

<xp:repeat value="#{repeatBean.quantities}" indexVar="index">
    <xp:inputText id="inputQty" value="#{repeatBean.quantities[index]}">
        <xp:eventHandler event="onchange" submit="true"
            execMode="partial" refreshMode="norefresh" script="console.log(Date.now())" />
    </xp:inputText>
</xp:repeat>

Even if you were to choose the latter approach I don't understand your concern about getting hold of the new values when your save method is invoked. viewScope.v1 will for sure contain all the submitted values already, there's no need to loop through the components to get such new values; they're already there in your v1 Vector. Consider the following (again don't mind the different variable names):

<xp:repeat value="#{repeatBean.quantities}" indexVar="index">
    <xp:inputText id="inputQty" value="#{repeatBean.quantities[index]}" />
    <br/>
</xp:repeat>

<xp:button id="button1" value="Label">
    <xp:eventHandler event="onclick" submit="true"
        refreshMode="partial" refreshId="showMe" action="#{repeatBean.save}" />
</xp:button>

<br/>

<xp:text id="showMe" value="#{repeatBean.quantities}" />