4

I have a Repeat control in which I have a edit box which has passed a default value.There is a Delete button to delete that row.

just for test I have used a computed field along with the edit box.Computed field is also passed the same value as edit box.Now both computed Field and Edit Box has same value,When I click on Delete button randomly,it gets delete but only computed field updates properly in repeat control wherever deleted,

In case of Edit box,it shows the last record disappears. So the issue is, the value in edit box does not get update like computed field does.I have done the test by writing following code.

 <?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

    <xp:this.data>
        <xp:dominoDocument var="document1" formName="testing">
        </xp:dominoDocument>
    </xp:this.data>
    <xp:inputText id="inputText1" multipleSeparator=",">
        <xp:this.defaultValue><![CDATA[#{javascript:var v:java.util.Vector = new java.util.Vector();
v.add('1');v.add('2');v.add('3');v.add('4');v.add('5');v.add('6');
return v;}]]></xp:this.defaultValue>
    </xp:inputText>
    <xp:br></xp:br>
    <xp:repeat id="repeat1" rows="30" var="r" indexVar="i" first="0">
        <xp:this.value><![CDATA[#{javascript:return getComponent("inputText1").getValue();}]]></xp:this.value>
        <xp:br></xp:br>
        <xp:div style="text-align:center">
            <xp:label value="#{javascript:r}" id="label1"
                style="text-align:center">
            </xp:label>
            <xp:button value="Delete" id="button1">
                <xp:eventHandler event="onclick" submit="true"
                    refreshMode="complete">
                    <xp:this.action><![CDATA[#{javascript:var v:java.util.Vector = getComponent("inputText1").getValue();
if(v != null){
var sdtString =  getComponent("inputText2").getValue();
if(v.contains(sdtString))
v.remove(sdtString);
};}]]></xp:this.action>
                </xp:eventHandler>
            </xp:button>
            <xp:inputText id="inputText2">
                <xp:this.defaultValue><![CDATA[#{javascript:getComponent("label1").getValue();}]]></xp:this.defaultValue>
            </xp:inputText>
        </xp:div>
        <xp:br></xp:br>
    </xp:repeat>
</xp:view>

This is the example code for testing to get the exact issue.

Edit 1: Real Scenario

We have an application to select multiple dates for a meeting and hence using the notes free time we mark multiple dates and then users are allowed to edit/delete the same in another window..Since, it was not possible/feasible enough to save all the fields in SSJS, we rather preferred binding each field with the data-source under the repeat control by using custom properties of the custom control (hope I am making some sense). Every fields is mapped as @chintan pointed out as follows:

dataSource[compositeData.to]

As described in the first part of the question the fields are not getting updated since we set them using default values. However, based on the suggestion we tried to set the field using the script library which does work well, however, might seem stupid but it messes the date field. When we set the value using the following:

var d:java.util.Date = new java.util.Date(compositeData.selectedDate);
getComponent("from").setValue(d);

It jumbles up the month, date and year field and shows a complete different value (the same code works well when put as the default value).

Hope this makes sense.

Any kind of solution can be appreciated.

Ajit Hogade
  • 1,072
  • 9
  • 29

2 Answers2

2

inputText2's defaultValue gets executed only once at first page load. Then the XPage memorized that repeat 1 has inputText2 defaultValue 1, repeat 2 has inputText2 defaultValue 2 and so on.

enter image description here

Example: as you can see in print log, inputText2's defaultValue doesn't get calculated again after deleting row 3 and later row 1.

Turn it around and set inputText2's value in label1's value code:

        <xp:label
            value="#{javascript:getComponent('inputText2').setValue(r); r}"
            id="label1"
            style="text-align:center">
        </xp:label>

then it will set inputText2's value properly. You don't need inputText2's defaultValue property anymore.

As an alternative you can define inputText2's value property and bind it to a row-specific data source or viewScope variable.

Knut Herrmann
  • 30,880
  • 4
  • 31
  • 67
  • Thanks, that indeed solves the problem here, however, in the real scenario we have a multiple fields in there (section and 2 dates to be precise), the second date is dependent on the value of the first date and it would break down after the first repeat as it won't update..the alternate approach would be to set everything using a hidden field, however, would that be a good approach? – Ajit Hogade May 16 '15 at 09:30
  • Also, regarding binding, the fields are present in a custom control which is iterated inside the repeat control and all the bindings are set using the custom properties, so I believe the alternative won't work here? Please correct me if I am wrong.. – Ajit Hogade May 16 '15 at 09:31
  • Sorry, let me interrupt too as we both are working on the same thing..well, first of all thank you so much for all the replies..the binding is already established as "compositeData.dataSource[compositeData.from]" and it is kind of necessary to store all the values on the save event..so, as per my knowledge we won't be able to follow the last suggestion, right? Please do correct me if I am wrong.. – Chintan Parekh May 16 '15 at 10:06
  • Sorry, I had to rollback my custom control suggestion as it doesn't make sense for this example as you would need access to custom control's inputText2's value in delete button. I feel that your test example simplifies your real code too much. What kind of data source did you define and what are the repeat values really? Multi value fields? Documents? – Knut Herrmann May 16 '15 at 10:13
  • Well, ..Delete functionality seems to work correctly.,.we found a way around to that..we grab the value dynamically in the iterator by using the index variable to pull the value from the vector which is iterated.its difficult to kind of share the code here..as even if I share most of the fields are dependent on a settings document and would just crash down on your side.. will just get the question edited with the explanation of the real scenario.. – Chintan Parekh May 16 '15 at 10:29
  • We have did it that way and it done!.Sorry for the late reply.even both the solution are useful. – Ajit Hogade May 19 '15 at 10:00
1

As you described in your "Edit 1 Real Scenario", you want to edit and delete pairs of dates. I created the following example. Instead of dates I just use strings for simplicity. Keep the dates in a viewScope variable and edit/delete them right there:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view
    xmlns:xp="http://www.ibm.com/xsp/core">
    <xp:this.beforePageLoad><![CDATA[#{javascript:viewScope.dates=[
    {"from":"a", "to":"b"},
    {"from":"c", "to":"d"},
    {"from":"x", "to":"y"}];}]]></xp:this.beforePageLoad>
    <xp:br />
    <xp:repeat
        id="repeat1"
        rows="30"
        var="r"
        indexVar="i"
        value="#{viewScope.dates}">
        <xp:br></xp:br>
        <xp:div>
            <xp:button
                value="Delete"
                id="button1">
                <xp:eventHandler
                    event="onclick"
                    submit="true"
                    refreshMode="complete">
                    <xp:this.action><![CDATA[#{javascript: viewScope.dates.remove(i);
                    }]]></xp:this.action>
                </xp:eventHandler>
            </xp:button>
            <xp:inputText
                id="inputText1"
                value="#{r.from}">
            </xp:inputText>
            <xp:inputText
                id="inputText2"
                value="#{r.to}">
            </xp:inputText>
            <xp:button
                value="Update"
                id="button2">
                <xp:eventHandler
                    event="onclick"
                    submit="true"
                    refreshMode="complete">
                    <xp:this.action><![CDATA[#{javascript: "";
                    }]]></xp:this.action>
                </xp:eventHandler>
            </xp:button>
        </xp:div>
        <xp:br></xp:br>
    </xp:repeat>
    <xp:text
        escape="false"
        id="computedField1">
        <xp:this.value><![CDATA[#{javascript:
            var length = viewScope.dates.length;
            var result = "";
            for (var i = 0; i < length; i++) {
                result += viewScope.dates[i].from + " - " + viewScope.dates[i].to + "<br />";
            }
            result
        }]]></xp:this.value>
    </xp:text>
</xp:view>

Create the viewScope variable as an array of objects.

Knut Herrmann
  • 30,880
  • 4
  • 31
  • 67