0
votes

I have a field inside a repeat control. Right now am using a viewScope in the onChange event to capture the field values inside the repeat control. Each time the field has to partial refreshes in order to get the value set in the scope variable.

The problem here is when the users set the focus outside the repeat control, the focus is not set until the partial refresh of the field is completed. Sometimes this partial refresh is too slow when user is accessing a remote domino server. Is there a effective way to capture the values inside the repeat control when the form is submitted?

The idea is to create fields dynamically when user click on the add button. The problem happen when you move the focus from the field inside the repeat control to the field outside the repeat control. The focus is not set, until the partial refresh of field inside the repeat control is completed. You may not occur this scenario, if the server is running locally on your machine. The below code shows the usage of repeat control to create fields dynamically

<xp:button value="Add Objects" id="addNavObj">
    <xp:eventHandler event="onclick" submit="true"
        refreshId="objLine" refreshMode="partial" id="eventHandler24">
        <xp:this.action><![CDATA[#{javascript:viewScope.rowItems=viewScope.rowItems+1;getComponent("navObjRep").setValue(parseInt(viewScope.rowItems));}]]></xp:this.action>
    </xp:eventHandler>
</xp:button>
<xp:repeat rows="30" var="rowData" indexVar="rowIndex"
    repeatControls="false" first="0" value="#{javascript:viewScope.rowItems}"
    id="navObjRep" style="width:800.0px">
    <xp:panel style="width:800.0px" id="objLine">
        <xp:table style="width:800.0px">
            <xp:tr>
                <xp:td style="width:245.0px">
                    <xp:inputText id="objType" style="width:130.0px">
                        <xp:typeAhead mode="full" minChars="1" ignoreCase="true"
                            id="typeAhead4" rendered="false">
                        </xp:typeAhead>
                    </xp:inputText>
                </xp:td>
                <xp:td style="width:46.0px">
                    <xp:inputText id="objCode">
                        <xp:eventHandler event="onchange" submit="true"
                            refreshMode="partial" refreshId="objCode" id="eventHandler3">
                            <xp:this.action><![CDATA[#{javascript:viewScope['objCode'+rowIndex] = getComponent("objCode").getValue()}]]></xp:this.action>
                        </xp:eventHandler>
                    </xp:inputText>
                </xp:td>
                <xp:td style="width:300.0px">
                    <xp:inputTextarea id="objDesc" style="height:40.0px;width:200.0px">
                        <xp:eventHandler event="onclick" submit="false" id="eventHandler40"></xp:eventHandler>
                        <xp:eventHandler event="onchange" submit="true"
                            refreshMode="partial" refreshId="objDesc" id="eventHandler4">
                            <xp:this.action><![CDATA[#{javascript:viewScope['objDesc'+rowIndex] = getComponent("objDesc").getValue()}]]></xp:this.action>
                        </xp:eventHandler>
                    </xp:inputTextarea>
                </xp:td>
            </xp:tr>
        </xp:table>
    </xp:panel>
</xp:repeat>
3
You need to take one step back: What is the functionality you try to achieve? Eventually the solution is completely different from your approach. So share a little more! - stwissel
Just to make clear I understand you: When you click the button you refresh the entire repeat control and you also do that in the onChange handler for inputTextArea (why that one? OnChange fires quite often and unless you have a checkbox/radio/dropdown it makes a lot of problems in roundtripping). The response takes some time (network, cpu), so once the data comes back it messes up the focus in the client. - What user experience are you trying to achieve? I'm still missing that part. - stwissel
In the above tag, each time the Add object button is clicked, the repeat control is refreshed to add new table rows with fields dynamically created. The onChange event with partial refresh is set for all fields inside to capture the value inside the field and set in the viewScope .This logic will help, if user wants to add new line items for their purchase order or adding timesheet for each activity done for that day - shibu
Bad design. Never touch the on change event of a text field. You create a refresh nightmare - stwissel

3 Answers

0
votes

Don't use the onChange event of an edit box for a partial refresh - you create an experience night mare. Excercise 23 has all you need.

0
votes

Its just a simple, example for a repeat control with a variable number of input and computed Fields.Hope it helps you to solve your problem.

    <xp:this.beforePageLoad><![CDATA[#{javascript:var languages:java.util.Vector = @Explode("de,en,pl",",");
                viewScope.put("allLanguages",languages);
                viewScope.put("selectedLanguages", languages)}]]>
    </xp:this.beforePageLoad>

<xp:checkBoxGroup id="checkBoxGroup1" value="#{viewScope.selectedLanguages}">
    <xp:this.defaultValue><![CDATA[#{javascript:return viewScope.get( "allLanguages" );}]]></xp:this.defaultValue>
    <xp:eventHandler event="onchange" submit="true" refreshMode="complete">
         <xp:this.action><![CDATA[#{javascript:// full update //partial update}]]></xp:this.action>
    </xp:eventHandler>
    <xp:selectItems>
      <xp:this.value><![CDATA[#{javascript:return viewScope.get( "allLanguages" );}]]></xp:this.value>
    </xp:selectItems>
</xp:checkBoxGroup>

<xp:repeat id="repeat1" rows="30" var="varcollection" repeatControls="true">
            <xp:this.value><![CDATA[#{javascript:return viewScope.get( "allLanguages" );}]]></xp:this.value>

    <xp:span>
        <xp:this.rendered><![CDATA[#{javascript:var vec:java.util.Vector = viewScope.get( "selectedLanguages" );
    return @IsMember(varcollection,vec);
    }]]></xp:this.rendered>

                <xp:label id="label1">
                    <xp:this.value><![CDATA[#{javascript:return varcollection + ": ";}]]></xp:this.value>
                </xp:label>

                <xp:inputText id="inputText1" loaded="true">
                    <xp:this.value><![CDATA[${javascript:var fieldName = "Help_" + varcollection;
    return '#{viewScope.' + fieldName + '}';}]]></xp:this.value>

                    <xp:eventHandler event="onchange" submit="true"
                        refreshMode="partial" refreshId="computedField1">
                    </xp:eventHandler></xp:inputText>
                &#160;&#160;<xp:text escape="true" id="computedField4"><xp:this.value><![CDATA[#{javascript:var fieldName = "Help_" + varcollection;
    return '#{viewScope.' + fieldName + '}';}]]></xp:this.value></xp:text>&#160;&#160;
                <xp:text escape="true" id="computedField1">
                    <xp:this.value><![CDATA[${javascript:var fieldName = "Help_" + varcollection;
    return '#{viewScope.' + fieldName + '}';
    }]]></xp:this.value>
                </xp:text>

                <xp:br></xp:br>

            </xp:span>

         </xp:repeat>    <xp:br></xp:br>
                 <xp:button value="Submit" id="button1">
                 <xp:eventHandler event="onclick" submit="true" refreshMode="complete" immediate="false" save="true"></xp:eventHandler></xp:button>
                 <xp:br></xp:br>
                 <xp:br></xp:br>
                 <xp:text escape="true" id="computedField3"><xp:this.value><![CDATA[#{javascript:return  "value1 = " +viewScope["Help_de"] + 
                    "value2 = " +viewScope["Help_en"] + 
                    "value3 = " +viewScope["Help_pl"]}]]></xp:this.value></xp:text>

The last computet field: computetdField3 will get the values 'onSubmit' and the others onChange.

0
votes

I strugled for a few hours with about the same problem. I have a repeat build up from different views and even do some consolidation on the result to show a nice input matrix of 3 field per row. I want to create new documents for every line that has fields filled in in the repeat.

Partial refresh is indeed a nightmare.

Finaly I ended up with client side script onfocus and onChange events to add my data into a hidden field on the page. I concatenate the 3 fields per row and put them in the hidden field seperated by a §.
When pressing the submit button I just get server side the value of that hidden field, @Explode("§") it and run trough the newly created array and create documents from them.