Bruce Stemplewski
Bruce Stemplewski

Reputation: 1343

Hiding based on previous combo box choice in xpages?

I have 3 comboboxes

Combo1 Combo2 Combo3

If Combo1 is blank (no selection) then combo2 is hidden. If Combo2 is blank then Combo3 is hidden.

If Combo1 is changed, it blanks Combo2, if Combo2 is changed it blanks Combo3.

This is because Combo2 choices are determined by Combo1 and Combo3 choices by Combo2. This is all working well.

What is happening if I change Combo1 then Combo2 and Combo3 are being blanked just as expected but Combo3 is not being hidden. If all I do is change Combo1 again, Combo3 is hidden. It is almost like I need 2 update events.

Is there any way around this?

Update

The issue seems to be with comboboxes that have computed selection values. In the sample below, changing the State should cause the ShowRoom scope variable to be "0" Changing Floor sets it to "1". A Computed Field will show the current value of the scope variable. It appears the onChange event of the State combo box is not being triggered. If you change the city selection from computed to static values then it works fine.

    Not&#160;Working (Computed&#160;Selections)<xp:table style="width:100%" id="tblSurvey2">

    <xp:tr>
        <xp:td style="width:300px">
            <xp:label value="*State" style="width:66.0px" styleClass="FieldLabel" id="label1">
            </xp:label>

        </xp:td>
        <xp:td style="width:745.0px">

            <xp:comboBox id="comboBoxState2" style="width:173.0px">



                <xp:eventHandler event="onchange" submit="true"
                    refreshMode="partial" refreshId="tblSurvey2">
                    <xp:this.action><![CDATA[#{javascript:viewScope.put("ShowRoom2","0");}]]></xp:this.action>
                </xp:eventHandler>






                <xp:selectItem itemLabel="AL"></xp:selectItem>
                <xp:selectItem itemLabel="CA"></xp:selectItem>
                <xp:selectItem itemLabel="NY"></xp:selectItem>
                <xp:selectItem itemLabel="PA"></xp:selectItem>
            </xp:comboBox>
            State =&#160;
            <xp:text escape="true" id="computedField1">
                <xp:this.value><![CDATA[#{javascript:getComponent("comboBoxState2").getValue()}]]></xp:this.value>
            </xp:text>
            &#160;&#160;&#160;Show Room =&#160;
            <xp:text escape="true" id="computedField4">
                <xp:this.value><![CDATA[#{javascript:viewScope.get("ShowRoom2");}]]></xp:this.value>
            </xp:text>
        </xp:td>
    </xp:tr>
    <xp:tr id="tr1">

        <xp:td style="width:300px">
            <xp:label value="*City" style="width:66.0px" styleClass="FieldLabel" id="label2">
            </xp:label>
        </xp:td>
        <xp:td style="width:785.0px">
            <xp:comboBox id="comboBoxCity2" style="width:175.0px">

                <xp:eventHandler event="onclick" submit="true"
                    refreshMode="norefresh" id="eventHandler1">
                </xp:eventHandler>
                <xp:eventHandler event="onchange" submit="true"
                    refreshMode="partial" refreshId="tblSurvey2" id="eventHandler2"></xp:eventHandler>










                <xp:selectItems>
                    <xp:this.value><![CDATA[#{javascript:new Array(getComponent("comboBoxState2").getValue() + " City1", getComponent("comboBoxState2").getValue() + " City2", getComponent("comboBoxState2").getValue() + " City3");}]]></xp:this.value>
                </xp:selectItems>
            </xp:comboBox>
        </xp:td>
    </xp:tr>

    <xp:tr id="tr2">

        <xp:td style="width:300px">
            <xp:label value="*Floor" style="width:66.0px" styleClass="FieldLabel" id="label3">
            </xp:label>
        </xp:td>
        <xp:td style="width:745.0px">
            <xp:comboBox id="comboBoxFloor2" style="width:89.0px">

                <xp:eventHandler event="onclick" submit="true" refreshMode="norefresh" id="eventHandler5">
                </xp:eventHandler>
                <xp:eventHandler event="onchange" submit="true"
                    refreshMode="partial" refreshId="tblSurvey2" id="eventHandler7">
                    <xp:this.action><![CDATA[#{javascript:viewScope.put("ShowRoom2","1");}]]></xp:this.action>
                </xp:eventHandler>




                <xp:selectItem itemLabel="Floor1"></xp:selectItem>
                <xp:selectItem itemLabel="Floor2"></xp:selectItem>
                <xp:selectItem itemLabel="Floor3"></xp:selectItem>
            </xp:comboBox>
        </xp:td>
    </xp:tr>
    <xp:tr id="tr3">
        <xp:this.rendered><![CDATA[#{javascript:viewScope.get("ShowRoom2") == "1";}]]></xp:this.rendered>
        <xp:td>
            <xp:label value="*Room" style="width:66.0px" styleClass="FieldLabel" id="label6">
            </xp:label>
        </xp:td>
        <xp:td>
            <xp:comboBox id="comboBoxRoom2" style="width:89.0px">                   
                <xp:selectItem itemLabel="A"></xp:selectItem>
                <xp:selectItem itemLabel="B"></xp:selectItem>
                <xp:selectItem itemLabel="C"></xp:selectItem>
            </xp:comboBox>
        </xp:td>
    </xp:tr>
  </xp:table>
<xp:br></xp:br>
<xp:br></xp:br>

Upvotes: 0

Views: 2574

Answers (2)

stwissel
stwissel

Reputation: 20384

I presume you are using partial refresh to do this? So you have

C1 -> C2/C3
C2 -> C3

Since you only can have one partial refresh target you need to wrap C2/C3 into a panel and target that one for C1's partial refresh. Also check how you hide C3. you might want to use a viewScope variable to manage the states and depend your visibility on that one.

Update: You should bind your fields to viewScope variables, not set extra values. Also: a combobox shows when the bound variable value is missing or has no match the first value, but doesn't reflect it. So in a combobox you always need to have a first value that makes sense "-Please select|-" is common or looking up the actual first value. In your case the "please select" makes sense. You also might consider if you really want to hide the fields (that becomes a "mystery meat" navigation) or just update the possible selections (remove the rendered properties from the example below to see how it works).

Here you go:

<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:table style="width:100%" id="tblSurvey2">
    <xp:tr>
        <xp:td style="width:300px">
            <xp:label value="*State" style="width:66.0px"
                styleClass="FieldLabel" id="label1">
            </xp:label>
        </xp:td>
        <xp:td style="width:745.0px">
            <xp:comboBox id="comboBoxState2" style="width:173.0px"
                value="#{viewScope.selectedState}">
                <xp:eventHandler event="onchange" submit="true"
                    refreshMode="partial" refreshId="tblSurvey2" id="eventHandler2">
                    <xp:this.action><![CDATA[#{javascript:viewScope.selectedCity = "-";
viewScope.selectedFloor = "-";
       viewScope.selectedRoom = "-";}]]></xp:this.action>
                </xp:eventHandler>
                <xp:selectItem itemLabel="-Please select-"
                    itemValue="-" id="selectItem1">
                </xp:selectItem>
                <xp:selectItem itemLabel="AL" itemValue="AL" id="selectItem2"></xp:selectItem>
                <xp:selectItem itemLabel="CA" itemValue="CA" id="selectItem3"></xp:selectItem>
                <xp:selectItem itemLabel="NY" itemValue="NY" id="selectItem4"></xp:selectItem>
                <xp:selectItem itemLabel="PA" itemValue="PA" id="selectItem5"></xp:selectItem>
            </xp:comboBox>

        </xp:td>
    </xp:tr>
    <xp:tr id="tr1" style="background-color:rgb(253,250,227)">
        <xp:this.rendered><![CDATA[#{javascript:viewScope.selectedState && (viewScope.selectedState != "-")}]]></xp:this.rendered>
        <xp:td style="width:300px">
            <xp:label value="*City" styleClass="FieldLabel"
                id="label2">
            </xp:label>
        </xp:td>
        <xp:td style="width:785.0px">
            <xp:comboBox id="comboBoxCity2"
                value="#{viewScope.selectedCity}">
                <xp:eventHandler event="onchange" submit="true"
                    refreshMode="partial" id="eventHandler1" refreshId="tblSurvey2">
                    <xp:this.action><![CDATA[#{javascript:viewScope.selectedFloor = "-";
  viewScope.selectedRoom = "-";}]]></xp:this.action>
                </xp:eventHandler>
                <xp:selectItems id="selectItems1">
                    <xp:this.value><![CDATA[#{javascript:var hasState = viewScope.selectedState && (viewScope.selectedState != "-");
 var result = ["-Please select-|-"];
 var cities = viewScope.selectedState + " " + ["City1","City2","City3"];
 for (var x in cities) {
result.push(cities[x]);
 };
 return hasState ? result : "Please select a state first|-"; 
 }]]></xp:this.value>
                </xp:selectItems>
            </xp:comboBox>
        </xp:td>
    </xp:tr>

    <xp:tr id="tr2">

        <xp:this.rendered><![CDATA[#{javascript:viewScope.selectedCity && (viewScope.selectedCity != "-")}]]></xp:this.rendered>
        <xp:td style="width:300px">
            <xp:label value="*Floor" style="width:66.0px"
                styleClass="FieldLabel" id="label3">
            </xp:label>
        </xp:td>
        <xp:td style="width:745.0px">
            <xp:comboBox id="comboBoxFloor2"
                value="#{viewScope.selectedFloor}">

                <xp:eventHandler event="onchange" submit="true"
                    refreshMode="partial" id="eventHandler5" refreshId="tblSurvey2">
                    <xp:this.action><![CDATA[#{javascript:viewScope.selectedRoom = "-";}]]></xp:this.action>
                </xp:eventHandler>
                <xp:selectItems id="selectItems2">
                    <xp:this.value><![CDATA[#{javascript:var hasCity = viewScope.selectedCity && (viewScope.selectedCity != "-");
  var result = ["-Please select-|-"];
  var floors = viewScope.selectedCity + " " + ["Floor1","Floor2","Floor3"];
  for (var x in floors) {
result.push(floors[x]);
  };
  return hasCity ? result : "Please select a city first|-"; 
  }]]></xp:this.value>
                </xp:selectItems>
            </xp:comboBox>
        </xp:td>
    </xp:tr>
    <xp:tr id="tr3" style="background-color:rgb(253,250,227)">

        <xp:this.rendered><![CDATA[#{javascript:viewScope.selectedFloor && (viewScope.selectedFloor != "-")}]]></xp:this.rendered>
        <xp:td>
            <xp:label value="*Room" style="width:66.0px"
                styleClass="FieldLabel" id="label6">
            </xp:label>
        </xp:td>
        <xp:td>
            <xp:comboBox id="comboBoxRoom2"
                value="#{viewScope.selectedRoom}">
                <xp:selectItems id="selectItems3">
                    <xp:this.value><![CDATA[#{javascript:var hasFloor = viewScope.selectedFloor && (viewScope.selectedFloor != "-");
    var result = ["-Please select-|-"];
    var rooms = viewScope.selectedFloor + " " + ["Room A","Room B","Room C"];
    for (var x in rooms) {
    result.push(rooms[x]);
  };
   return hasFloor ? result : "Please select a floor first|-"; }]]></xp:this.value>
                </xp:selectItems>
                <xp:eventHandler event="onchange" submit="true"
                    refreshMode="partial" refreshId="computedField4" id="eventHandler3">
                </xp:eventHandler>
            </xp:comboBox>
        </xp:td>
    </xp:tr>
    <xp:tr>
        <xp:td>Current variables</xp:td>
        <xp:td>State:
<xp:text escape="true" id="computedField1" value="#{viewScope.selectedState}">
</xp:text>
<xp:br></xp:br>
City:
<xp:text escape="true" id="computedField2" value="#{viewScope.selectedCity}">
</xp:text>
<xp:br></xp:br>
Floor:
<xp:text escape="true" id="computedField3" value="#{viewScope.selectedFloor}">

</xp:text>
<xp:br></xp:br>Room:
<xp:text escape="true" id="computedField4" value="#{viewScope.selectedRoom}">
    </xp:text></xp:td></xp:tr></xp:table></xp:view>

You could simplify the code by moving the "please select" into its own value item and use a function rather repeating code, but you get the idea.

Upvotes: 2

Simon McLoughlin
Simon McLoughlin

Reputation: 8465

you can execute multiple partial updates with some javascript. Take a look at this:

http://xpageswiki.com/web/youatnotes/wiki-xpages.nsf/dx/Work_with_events_and_partial_or_full_refresh

Upvotes: 1

Related Questions