0
votes

I want to refresh a XPages' control, that displays data based on input of a ListBox. I use a Backing Bean that holds the data. The Backing Bean is connected by EL Value Binding. For a Computed Text Control, the Backing Bean returns the first selected value of the listData property.

public class BackingBean implements Serializable {
    private static final long serialVersionUID = 1L;

    private List listData;
    private String displayData;

    public BackingBean() {}

    public List getListData() {
        System.out.println("getListData()");
        return listData;
    }

    public void setListData(List listData) {
        System.out.println("setListData()");
        this.listData = listData;
    }


    public String getDisplayData() {
        System.out.println("getDisplayData()");

        if(listData != null && listData.size() > 0) {
            return (String) listData.get(0);    
        } 

        return "NO LIST DATA";
    }

}

Here is my XPage code:

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

    <xp:div id="refreshMe">
        <xp:listBox id="listBox1">
            <xp:this.value><![CDATA[#{backingBean.listData}]]></xp:this.value>
            <xp:selectItem itemLabel="Value 1"></xp:selectItem>
            <xp:selectItem itemLabel="Value 2"></xp:selectItem>
            <xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="refreshMe">
            </xp:eventHandler>
        </xp:listBox>

    <xp:text escape="true" id="computedField1" value="#{backingBean.displayData}"></xp:text>
</xp:div>

</xp:view>

The problem is, on partial refresh, the data will be sent to the server, but the setListData setter is never called. The computed text only shows "NO LIST DATA".

view:_id1:listBox1:Value 1 // <-- selected option is sent to the server
$$viewid:!e9x9cl6xse!
$$xspsubmitid:view:_id1:_id298
$$xspexecid:
$$xspsubmitvalue:
$$xspsubmitscroll:0|0
view:_id1:view:_id1

How can I do a partial refresh off a control, whose value relies on value bound data of another control?

2

2 Answers

1
votes

Found cause and solution!

When I set disableValidators to true the setListData setter will be called and the Backing Bean gets updated.

<xp:listBox id="listBox1">
    <xp:this.value><![CDATA[#{controller.listData}]]></xp:this.value>
    <xp:selectItem itemLabel="Value 1"></xp:selectItem>
    <xp:selectItem itemLabel="Value 2"></xp:selectItem>
    <xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="refreshMe" disableValidators="true"></xp:eventHandler>
</xp:listBox>

To be honest, I also want to update data by using XSP.partialRefreshPost. When I try this, I'm not able to disable validation out of the box. But Sven Hasselbach posted a solution for this: https://stackoverflow.com/a/21931796/4735030 (In short: Implement a PhaseListener that disables Validation on demand.)

The event handler, that uses XSP.partialRefreshPost looks like this:

<xp:eventHandler event="onchange" submit="false">
    <xp:this.script><![CDATA[   
        XSP.partialRefreshPost(#{id:refreshMe}', {'params': {'disableValidation':true}});
    ]]></xp:this.script>
</xp:eventHandler>
0
votes

Try adding a setListData(String listData) method as well. "1" is not a List, so I wouldn't expect it to call your current method. I'm also not sure whether an xp:listBox maps to a List or a Vector. I would expect it to map to a Vector.