Search code examples
mobilexpagesxpages-extlibxpages-ssjs

Can a mobile app page determine what mobile app page called it and what was selected?


My issues tracking application has several categories (Client, AssignedTo, Module/Type, Priority, Status, Build, etc). There are several views that have two categorized columns (EG: Client and AssignedTo, Client and Module, AssignedTo and Priority, PPriority and Client,etc.

I am implementing mobile pages using the XPages Mobile controls. I want to streamline things so the the selection of the view on the mobile home page drives to a page for selecting the appropriate first category which, in turn drives to a page for selecting the second category. What I am not figuring out, is once the selection of the first categories value is done, and the second category selection page is open, what the value selected before was?

Here is my sample page so far:

<xe:singlePageApp
    id="singlePageApp1"
    selectedPageName="mhome">
    <xe:appPage
        id="appPage1"
        pageName="mhome">
        <xe:djxmHeading
            id="djxmHeading1"
            label="Home">
        </xe:djxmHeading>
        <xe:djxmRoundRectList
            id="djxmRoundRectList1">
            <xe:djxmLineItem
                id="djxmLineItem1"
                label="Issues by Client By Assigned To"
                moveTo="selectClient1">
            </xe:djxmLineItem>
            <xe:djxmLineItem
                id="djxmLineItem2"
                label="Issues by Client By Module"
                moveTo="selectClient2">
            </xe:djxmLineItem>
        </xe:djxmRoundRectList>
    </xe:appPage>
    <xe:appPage
        id="appPage2"
        pageName="selectClient1"
        resetContent="true">
        <xe:djxmHeading
            id="djxmHeading2"
            label="Select Client"
            moveTo="mhome"
            back="back">
        </xe:djxmHeading>
        <xp:panel>
            <xp:this.data>
                <xp:dominoView
                    var="view1"
                    viewName="ByClientAssignedTo">
                </xp:dominoView>
            </xp:this.data>
            <xe:djxmRoundRectList
                id="djxmRoundRectList2">
                <xp:repeat
                    id="repeat1"
                    rows="30"
                    value="#{javascript:view1.getColumnValues(0);}"
                    var="client"
                    indexVar="clidx">
                    <xe:djxmLineItem
                        id="djxmLineItem3"
                        label="#{javascript:client}"
                        moveTo="selectAssignedTo1">
                    </xe:djxmLineItem>
                </xp:repeat>
            </xe:djxmRoundRectList>
        </xp:panel>
    </xe:appPage>
    <xe:appPage
        id="appPage3"
        pageName="selectClient2"
        resetContent="true">
        <xe:djxmHeading
            id="djxmHeading3"
            label="Select Client (2)"
            moveTo="mhome"
            back="back">
        </xe:djxmHeading>
        <xp:panel>
            <xp:this.data>
                <xp:dominoView
                    var="view1"
                    viewName="ByClientAssignedTo">
                </xp:dominoView>
            </xp:this.data>
            <xe:djxmRoundRectList
                id="djxmRoundRectList3">
                <xp:repeat
                    id="repeat2"
                    rows="30"
                    value="#{javascript:view1.getColumnValues(0)}"
                    var="client"
                    indexVar="clidx">
                    <xe:djxmLineItem
                        id="djxmLineItem4"
                        label="#{javascript:client}"
                        moveTo="selectType1">
                    </xe:djxmLineItem>
                </xp:repeat>
            </xe:djxmRoundRectList>
        </xp:panel>
    </xe:appPage>
    <xe:appPage
        id="appPage4"
        pageName="selectAssignedTo1"
        resetContent="true">
        <xe:djxmHeading
            id="djxmHeading4"
            back="back"
            label="Select Assigned To"
            moveTo="selectClient1">
        </xe:djxmHeading>
        <xp:text
            escape="true"
            id="computedField1">
            <xp:this.value><![CDATA[#{javascript:"What was selected on the previous page?"}]]></xp:this.value>
        </xp:text>
    </xe:appPage>
</xe:singlePageApp>

Solution

  • Technique 1:
    The djxmLineItem event supports the onClick event event though there is no documentation for it within Xpages (that I have found). It is documented as part of dojo under the dojox.mobile ListItem.

    If necessary create an onClick event for another control and copy the code under the xe:djxmLineItem tag. You can use deferred evaluation (#) to access the indexVar to identify which ListItem inside the repeat has been clicked.

    A major drawback of adding an event handler is that you must trigger a partial refresh on something inside the target page in order to cause its content to be rendered. This in turn means that pages content must be preloaded in order for the refresh target to be available. This is most likely a bug in the current implementation of mobile controls but it can be a PAIN!.

    Technique 2:
    To track the pages AND the selected item without the above side effects. DOn't add an event handler. Instead... create the listitem in such a way that the "id" for the item is added as a parameter for the moveTo attribute.

    example:

    <xe:djxmRoundRectList id="menuList">
      <xp:repeat value="#{compositeData.view.listItems}"
        var="listItem" indexVar="menuIndex" id="listRepeat" rows="999">
        <xe:djxmLineItem id="listItem"
          label="#{listItem.label}" moveTo="#{compositeData.view.moveTo}&amp;id=#{listItem.id}&amp;clear=true"
          rightText="#{listItem.rightText}">
        </xe:djxmLineItem>
      </xp:repeat>
    </xe:djxmRoundRectList>
    

    The following code can be added to the bottom of the page to add an event listener for the transition event of every appPage.

    <xp:scriptBlock id="scriptBlock1">
        <xp:this.value>
            <![CDATA[XSP.addOnLoad(function(){
              dijit.registry.byClass("extlib.dijit.mobile.View").forEach(function(widget, index, hash){
              dojo.connect(widget, "onBeforeTransitionOut", function(moveTo, dir, transition, context, method){
              var deferred = adminService.setMoveTarget(moveTo);
            });
          });
        });
      ]]>
      </xp:this.value>
    </xp:scriptBlock>
    

    The event handler is calling a jsonRpcService that passes the details to a bean (before the page transition occurs).

    <xe:jsonRpcService id="jsonRpcService1" serviceName="adminService"
      state="true">
      <xe:this.methods>
        <xe:remoteMethod name="setMoveTarget"
          script="AdminSession.setMoveTarget(moveTo);return true;">
          <xe:this.arguments>
            <xe:remoteMethodArg name="moveTo"></xe:remoteMethodArg>
            </xe:this.arguments>
          </xe:remoteMethod>    
      </xe:this.methods>
    </xe:jsonRpcService>
    

    the setMoveTarget() method in the AdminSession bean should then be able to parse out the parameters to identify the selected item as well as track the page transition.

    Note: adding clear=true is a way of ensuring pageContent of a page is only reset when moving forward to a page and not when you move back to the same page.