0
votes

I am starting to get the dynamic nature of Xpages and am trying to make my coding more streamlined.

I am using the switchFacet cc in my xpages to control which custom control to load, depending on the value in a sessionScope variable.

To keep things simple I made the name of the cc match the sessionScope variable. So I ended up with the following code.

 <?xml version="1.0" encoding="UTF-8"?>
    <xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlnsstrong text:xc="http://www.ibm.com/xsp/custom"
        xmlns:xe="http://www.ibm.com/xsp/coreex">
        <xc:ccAppLayout>
            <xp:this.facets>
                <xc:ccAppNav xp:key="LeftColumn" />
                <xe:switchFacet id="switchFacet1" xp:key="facet_1"
                    selectedFacet="#{javascript:return sessionScope.pageSelected}">
                    <xp:this.facets>
                        <xc:cpApp2Title1Page1 xp:key="cpApp2Title1Page1" />
                        <xc:cpApp2Title2Page1 xp:key="cpApp2Title2Page1" />
                        <xc:cpApp2Title2Page2 xp:key="cpApp2Title2Page2" />
                        <xc:cpApp2Title3Page1 xp:key="cpApp2Title3Page1" />
                    </xp:this.facets>
                </xe:switchFacet>
            </xp:this.facets>
        </xc:ccAppLayout>
    </xp:view>

Not to bad, but it seems to me things would be even cleaner if I could just directly set the cc to be the sessionScope variable. That way the code for this Xpage wouldn't have to change between different Xpages. I could get by with just one Xpage.

Is there a way to do this, and is it even a good idea?

Bryan

=============================================== What I am looking for is something like this:

<?xml version="1.0" encoding="UTF-8"?>
    <xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlnsstrong text:xc="http://www.ibm.com/xsp/custom"
        xmlns:xe="http://www.ibm.com/xsp/coreex">     
        <xc:ccAppLayout>
            <xp:this.facets>
                <xc:ccAppNav xp:key="LeftColumn" />        
                    <xc:#{javascript:return sessionScope.pageSelected} xp:key="facet_1"></xc:#{javascript:return sessionScope.pageSelected}>
            </xp:this.facets>
        </xc:ccAppLayout>
    </xp:view>

============================================================== Knut,

That is a good suggestion, but as you indicated it only loads on page creation.

Is there a different way to do what I want, or is it just easier to leave the code as I originally had it?

<?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">
    <xc:ccAppLayout>
        <xp:this.facets>
            <xc:ccAppNav xp:key="LeftColumn" />
            <xp:include id="include1" xp:key="facet_1">
                <xp:this.pageName><![CDATA[${javascript:sessionScope.pageSelected + ".xsp"}]]></xp:this.pageName>
            </xp:include></xp:this.facets>
    </xc:ccAppLayout>
</xp:view>
3
You can always make a property of the custom control, is that what you are asking?Steve Zavocki

3 Answers

2
votes

You can use <xp:include... and "calculate" custom control's name:

<xp:include pageName="${sessionScope.yourCC}" />

The sessionScope variable has to contain the name of your custom control like "cpApp2Title1Page1.xsp". Don't forget ".xsp" at the end.

Be aware that pageName gets calculated only once at first page load.

I know from your previous question that you'd like to keep the possible pages flexible in a sessionScope variable. Assuming you have a sessionScope variable pages which contains all custom control names as an array then you'd use a repeat and put the xp:include in it:

<xp:repeat
    id="repeat1"
    rows="30"
    var="key"
    repeatControls="true"
    value="${sessionScope.pages}">
    <xp:panel
        rendered="#{javascript:sessionScope.pageSelected == key}">
        <xp:include
            pageName="${javascript:key + '.xsp'}" />
    </xp:panel>
</xp:repeat>

It will include all pages defined in sessionScope variable pages but render only the one page with the name contained in sessionScope variable pageSelected.

You'd include the code above instead your switchFacet.

1
votes

Could you create one custom control to rule them all? A CC that takes the name of the desired CC as a custom property, then renders only the one you want. So shove the switchFacet into a new custom control, e.g. ccAll.xsp:

<?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">
   <xe:switchFacet id="switchFacet1" selectedFacet="#{javascript:return compositeData.ccName}">
        <xp:this.facets>
            <xc:cc1 xp:key="cc1" />
            <xc:cc2 xp:key="cc2" />
            <xc:cc3 xp:key="cc3" />
        </xp:this.facets>
    </xe:switchFacet>
</xp:view>

Add a custom property of ccName to the custom control using the "property definition" tab in the CC's properties. Custom control custom property

Then add that to your XPage and pass in the sessionScope variable.

<xc:ccAll ccName="#{javascript:return sessionScope.pageSelected}"></xc:ccAll>
1
votes

A while ago I have created a component to switch custom controls on-the-fly. The code is available at github: https://github.com/hasselbach/domino-ccinjector

The component can inject custom components whenever you want: during a partial refresh or depending on a variable.