3
votes

I have used the Dynamic Content Control with a Dynamic Page formula a fair bit but it has always been computed on page load and not changed. I have been working on a test where I want to select what page to display based on a combo box and an onChange event. I have done a full refresh as well as several different partial refreshes, but it appears that the page is only computed on the page load. The pages that this calls don't do anything but display "Page One" "Page Two" etc. The print statements only print from the initial page load. I have done a partial refresh of "customeControlInclude" "dynamicContentView" and a full Update in the onChange event of the Combo Box, but none of these cause the dynamicControlView to change the page loaded.

So my question is "Is there a way to cause the dynamic Content Control to recompute and display appropriate page?

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xc="http://www.ibm.com/xsp/custom"
    xmlns:xe="http://www.ibm.com/xsp/coreex">
    <xp:this.resources>
        <xp:script src="/js Utils.jss" clientSide="false"></xp:script>
    </xp:this.resources>
    <xp:panel id="thisPage">

        <xp:text escape="true" id="computedField1" value="#{sessionScope.ssSelectedView}"></xp:text>
        &#160;
        <xp:br></xp:br>
        <xp:br></xp:br>

        <xp:comboBox id="comboBox1" value="#{sessionScope.ssSelectedView}"
            style="width:20%">
            <xp:selectItem itemLabel="Test One"></xp:selectItem>
            <xp:selectItem itemLabel="Test Two"></xp:selectItem>
            <xp:selectItem itemLabel="Test Three"></xp:selectItem>
            <xp:selectItem itemLabel="Test Four">
            </xp:selectItem>


            <xp:eventHandler event="onchange" submit="true"
                refreshMode="partial" refreshId="thisPage">
            </xp:eventHandler>
        </xp:comboBox>
        <xp:br></xp:br>
        <xp:panel id="panelView">
            <xp:table>
                <xp:tr>
                    <xp:td style="width:100.0%" valign="top">
                        <xe:dynamicContent id="dynamicContentView">
                            <xp:include id="customControlIncluder">
                                <xp:this.pageName>
                                    <![CDATA[${javascript:try{
    var debug:Boolean = true;
    if (debug) print("Select Page in xpMainInput.xsp");
    var viewName:String = sessionScope.ssSelectedView;
    var page:String = null;
    switch(viewName){
        case "test One" :
            page = "ccTestOne.xsp";
            break;
        case "Test Two" :
            page = "ccTestTwo.xsp";
            break;
        case "Test Three" :
            page = "ccTestThree.xsp";
            break;
        case "Test Four" :
            page = "ccTestFour.xsp";
            break
        //Add additional case statements for each additional Application
    }
    if (page == null){
        if (debug) print("Error in Main page is null ");
        return "ccTestOne.xsp";
    }else{
        if (debug) print("xpMain page = " + page)
        return page;
    }
}catch(e){
    print("Error Define Page in xpMain.xsp " + e.string());
}}]]>
                                </xp:this.pageName>
                            </xp:include>
                        </xe:dynamicContent>
                    </xp:td>

                </xp:tr>
            </xp:table>
        </xp:panel>
    </xp:panel>
</xp:view>
2
What happens if you change the page name to be computed each time (so change '<![CDATA[${javascript:try{' to '<![CDATA[#{javascript:try{')?Per Henrik Lausten
Will give that a try. ThanksBill F
per Henrik Lauston - when I change the "$" to a "#" then the SSJS getnerates an error on the lines <xp:include that "Required property "pageName" for xp:include is not present." and on the Line <xp:this.pageName error of "The value of the property pageName cannot be a run time binding." so it would appear that the pageName can only be defined on the page load.Bill F
Yes, I agree with your conclusionPer Henrik Lausten

2 Answers

2
votes

You can load different custom controls dynamically if you redirect to the same page instead of a full or partial refresh and write the desired custom control name into a session scope variable before.

Your test XPage could look like this then:

    <xp:comboBox id="comboBox1" value="#{sessionScope.ssSelectedView}"
        style="width:20%">
        <xp:selectItem itemLabel="Test One" itemValue="ccTestOne.xsp"></xp:selectItem>
        <xp:selectItem itemLabel="Test Two" itemValue="ccTestTwo.xsp"></xp:selectItem>
        <xp:selectItem itemLabel="Test Three" itemValue="ccTestThree.xsp"></xp:selectItem>
        <xp:selectItem itemLabel="Test Four" itemValue="ccTestFour.xsp"></xp:selectItem>

        <xp:eventHandler event="onchange" submit="true"
            refreshMode="norefresh">
            <xp:this.action><![CDATA[#{javascript:
                facesContext.getExternalContext().redirect(context.getUrl().toString())
            }]]></xp:this.action>
        </xp:eventHandler>
    </xp:comboBox>

    <xp:br></xp:br>

    <xp:panel id="panelView">
        <xp:table>
            <xp:tr>
                <xp:td style="width:100.0%" valign="top">
                    <xp:include id="customControlIncluder">
                        <xp:this.pageName>
                            <![CDATA[${javascript:
                                !sessionScope.ssSelectedView ? "ccTestOne.xsp" : sessionScope.ssSelectedView
                            }]]>
                        </xp:this.pageName>
                    </xp:include>
                </xp:td>
            </xp:tr>
        </xp:table>
    </xp:panel>

As an alternative, you can add all custom controls to your XPage with a repeat control with option repeatControls="true" and render only one custom control at a time depending on scope variable. This works with a partial refresh.

    <xp:comboBox id="comboBox1" value="#{sessionScope.ssSelectedView}"
        style="width:20%">
        <xp:selectItem itemLabel="Test One" itemValue="ccTestOne.xsp"></xp:selectItem>
        <xp:selectItem itemLabel="Test Two" itemValue="ccTestTwo.xsp"></xp:selectItem>
        <xp:selectItem itemLabel="Test Three" itemValue="ccTestThree.xsp"></xp:selectItem>
        <xp:selectItem itemLabel="Test Four" itemValue="ccTestFour.xsp"></xp:selectItem>

        <xp:eventHandler event="onchange" submit="true"
            refreshMode="partial" refreshId="repeatCc">
        </xp:eventHandler>
    </xp:comboBox>

    <xp:br></xp:br>

    <xp:panel id="panelView">
        <xp:table>
            <xp:tr>
                <xp:td style="width:100.0%" valign="top">
                    <xp:repeat
                        id="repeatCc"
                        rows="100"
                        repeatControls="true"
                        var="cc"
                        value="#{javascript:['ccTestOne.xsp','ccTestTwo.xsp','ccTestThree.xsp','ccTestFour.xsp']}">
                        <xp:include
                             pageName="${cc}"
                             rendered="#{javascript: !sessionScope.ssSelectedView ? (cc === 'ccTestOne.xsp') : (cc === sessionScope.ssSelectedView)}" />
                    </xp:repeat>
                </xp:td>
            </xp:tr>
        </xp:table>
    </xp:panel>
0
votes

As described above the value for the pageName can only be resolved on page load. I have used this block of code for dynamically defining the page to load in several places but they have always been when loading a new XPage so it has been working fine. In the code above I was trying to force the pageName to be recomputed on a partial refresh. I even tried a full update but that does not recompute the pageName. Wish it would but then .... :-)