I have a requirement for having several graphical buttons at the bottom of each screen of a Mobile App. I have used the logic found in Graham Acres NotesIn9 presentation (#121) to get the Mobile Control Tab Bar (xe.tabBar) to load at and stay at the bottom of the screen. However adding anything other than Tab Bar Buttons (xe:tabBarButton) causes the control to display off to the right of center, and not in the center or left justified as needed.
Here is code I tried:
<xe:tabBar
id="tabBar1">
<xe:this.dojoAttributes>
<xp:dojoAttribute
name="center"
value="true">
</xp:dojoAttribute>
</xe:this.dojoAttributes>
<xp:image
url="/BottomButtonHome.jpg"
id="image1">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="complete">
<xp:this.action>
<xe:moveTo
direction="Left to Right"
targetPage="homepage"
transitionType="slide">
</xe:moveTo>
</xp:this.action>
</xp:eventHandler>
</xp:image>
</xe:tabBar>
This resulted in a skewed to the right presentation and clicking the graphic did not successfully open the other page.
Since that did not work I tried a simple Panel control (xp:panel) with the graphics and that presented better but the links still fail to open the other page. Here is that code:
<xp:panel
style="height:54px;width:100%">
<xp:image
url="/bottomButtonHome.jpg"
id="image2">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="complete">
<xp:this.action>
<xe:moveTo
direction="Left to Right"
targetPage="homepage"
transitionType="slide">
</xe:moveTo>
</xp:this.action>
</xp:eventHandler>
</xp:image>
</xp:panel>
Take a page from Bootstrap and see if Font-Awesome has an icon that would suite you. Then simply add it to your button with the respective CSS class
Related
I try using image button to direct update the tab panel, Every time i click on the button it give an error message.
If you want to manually navigate to a given tabPanel you must invoke the tabbedPanel method to switch tab. For brevity's sake I post an example based on what you can do on the page itself without the proper intervention of a backing Java class:
<ul>
<li>
<xp:link id="link1" text="select 1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="tabbedPanel1"
action="#{javascript: tabbedPanel.setSelectedTab('tabPanel1')}">
</xp:eventHandler>
</xp:link>
</li>
<li>
<xp:link id="link2" text="select 2">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="tabbedPanel1"
action="#{javascript: tabbedPanel.setSelectedTab('tabPanel2')}">
</xp:eventHandler>
</xp:link>
</li>
</ul>
<xp:tabbedPanel id="tabbedPanel1" binding="#{tabbedPanel}">
<xp:tabPanel label="New Tab" id="tabPanel1">panel1</xp:tabPanel>
<xp:tabPanel label="New Tab2" id="tabPanel2">panel2
</xp:tabPanel>
</xp:tabbedPanel>
To invoke the tab change I grab hold of the tabbedPanel object. I create a handy handle by means of the binding property - binding="#{tabbedPanel}". At this point the tabbedPanel can be accessed from anywhere in the page.
I wrote a couple of links whose action parameter implements tabbedPanel.setSelectedTab('tabPanel1')}. The setSelectedTab parameter value corresponds to the tabPanel id. The refresh, this is important, is then performed on the tabbedPanel - tabbedPanel1 - and not the specific opened tabPanel.
I have a very simple XPage that contains two links and a dynamic content control. If I click on the Page 1 link the hash is set to #content=page1 then I click on Page 2 link and the hash is set to #content=page2. Now I click the browser's back button and the facet switches to page1 but the hash stays at #content=page2 and the browser's forward button is grayed out. It looks like the URL flickers to me so it might be getting overwritten but I can't say for sure.
I am using Extension Library version 901v00_16.20160128-1014 and I have tested using Chrome and Firefox.
My XPage:
<xp:link escape="true" styleClass="list-group-item" text="Page 1" id="link1">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" id="eventHandler2" refreshId="dynamicContent1">
<xp:this.action><![CDATA[#{javascript:var c = getComponent("dynamicContent1"); c.show("page1")}]]></xp:this.action>
</xp:eventHandler>
</xp:link>
<xp:link escape="true" styleClass="list-group-item" text="Page 2" id="link2">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" id="eventHandler1" refreshId="dynamicContent1">
<xp:this.action><![CDATA[#{javascript:var c = getComponent("dynamicContent1"); c.show("page2")}]]></xp:this.action>
</xp:eventHandler>
</xp:link>
<xe:dynamicContent id="dynamicContent1" partialEvents="true" useHash="true" defaultFacet="page1">
<xp:this.facets>
<xp:div id="page1" xp:key="page1">Page 1</xp:div>
<xp:div id="page2" xp:key="page2">Page 2</xp:div>
</xp:this.facets>
</xe:dynamicContent>
I have been using the Extension Library Demo database: Core_DynamicPage.xsp page as a reference and this seems to works fine in there.
After changing my xsp property for "Minimum Supported Release" from "Release 9.0.1" to "Minimum release required by the XPage features used" the issue went away.
I have a document that contains a rating custom control (xInvolve, which is excellent!). In this application, administrators want the ability to delete certain ratings for a certain document or all of them (bad ratings on purpose, new version of the document, corrections made to the document ...).
I am showing up the ratings in a view, in a dialog box (the extension Library dialog box, not a Dojo one). In that dialog box, I have a "Delete All" button. That button calls a SSJS function that deletes the rating documents for the document that is currently opened, but I want to refresh the panel that displays the rating, as it should now be empty.
So far, I was able to close the dialog box, but I can't seem to get the panel to refresh. Here's the code for the "Delete All" button:
<xp:button value="Delete All" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action>
<xp:actionGroup>
<xp:confirm
message="Are you sure you want to proceed?">
</xp:confirm>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:deleteAllRatings(pageDocument.getDocument().getUniversalID());
var c = getComponent("dialogPageRatings");
c.hide("PanelHeader")}]]></xp:this.script>
</xp:executeScript>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
The PanelHeader is the panel where the xRating control is inserted.
Should I try putting code in the onClose event of the dialog box? I tried but I didn't get more luck.
Thanks
So you can use client side code to achieve this. This is what we do:
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:var strClientCode = "$('#editDeliveryAddressDialog').modal('hide'); window.location.reload();"
view.postScript(strClientCode);}]]></xp:this.script>
</xp:executeScript>
Hope it helps.
Ben,
Here is a solution using the RPC control. This control allows you to call server code directly from clientside javascript. I have frequently used it to call java methods, but haven't used it to call a SSJS function in a library. I make the assumption that it would work the same.
<xe:jsonRpcService id="jsonRpcService1" serviceName="myRPC"
pathInfo="rpc">
<xe:this.methods>
<xe:remoteMethod name="callDeleteAllRatings">
<xe:this.script><![CDATA[deleteAllRatings(universalID)}]]></xe:this.script>
<xe:this.arguments>
<xe:remoteMethodArg name="universalID" type="string" />
</xe:this.arguments>
</xe:remoteMethod>
</xe:this.methods>
</xe:jsonRpcService>
You would not be able to use getComponent in the RPC, so you would need to pass the UNID. You could pass this to the clientside using a <xp:hiddenInput> when you launch the window. You would close the window in the same manner that you do now (I think).
To call the method of the service, you would use myRPC.callDeleteAllRatings("Open ATM", ""); Again, you call the RPC from clientside.
IMO, once you learn what the RPC can do for you, you wonder how you made due without it.
As Mark suggested in a comment above, you should be able to use the onHide property. For example if you wanted to refresh a panel with serverSide id panel1
<xe:dialog id="dialog1" title="Example Dialog"
onHide=" XSP.partialRefreshGet('#{id:panel1}'); ">
This is working for me
Can you not just do a partial refresh? I do that with a simple dialog like so...
<xp:button value="Save and Close" id="button2" styleClass="btn btn-primary">
<xp:eventHandler event="onclick"
submit="true" refreshMode="partial"
refreshId="panelRefresh"
disableValidators="true"
onComplete="$('#myModal').modal('hide');">
<xp:this.action><![CDATA[#{javascript:var value:string=getComponent("inputText1").value;
document1.replaceItemValue("modalTest",value)}]]>
</xp:this.action>
</xp:eventHandler>
</xp:button>
I have a submit button on top that's normally doing a partial refresh of the form.
When I added a fileUpload control that won't due, as I need to do a full refresh. But I only wish this to happen if the user has added a file to be uploaded. So if the file Upload is empty I want to use a partialRefresh to submit.
I can check if a file is added easily enough and I could have two buttons with different refresh modes and hide them using JS, but that's a clunky solution.
What I would like to do is change the refresh mode on the submit button depending on a submitted value in the current form.
Any ideas?
Thanks!
/J
You can do this by adding a second event handler to your button: One event handler is for a full refresh, the other one for the partial refresh.
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:div id="divRefresh">
<xp:label value="#{javascript:java.lang.System.currentTimeMillis()}" id="label1" />
<xp:label value="#{javascript:java.lang.System.currentTimeMillis()}" id="label2" />
</xp:div>
<xp:br></xp:br>
<xp:button value="Refresh" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.script>
<![CDATA[alert("Complete!"); return false;]]>
</xp:this.script>
</xp:eventHandler>
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="label2">
<xp:this.script>
<![CDATA[alert("Partial!");return true;]]>
</xp:this.script>
</xp:eventHandler>
</xp:button>
</xp:view>
The CSJS code in the events has to return false to stop the event.
I do this in http://www.intrapages.com when posting new stream content.
in the onchange event for the upload control I set a requestScope variable. and if that is set I perform a full refresh. works great
I'm working on an XPage for mobile users for an existing application. I want to use the mobile controls from the ExtLib for this.
I've build an XPage with a SinglePageApp and some AppPages on it. Now I want to build an AppPage with a search menu, a simple inputText and a button to start the search.
The inputText is bind to a sessionScope variable. I want to use the variable in a second appPage to get the search value and show a filtered/searched view.
The problem is the button. I'm not sure how to build this button to move to the other appPage. This is my last attempt, which fails with a runtime error.
Any idea how to get this running or what's wrong ?
Kind regards
Ingo
<xe:appPage id="appPage34" pageName="searchPage" preload="true" resetContent="true">
<xe:djxmHeading id="djxmHeading34" label="Search..." back="Home" moveTo="home">
</xe:djxmHeading>
<xp:inputText id="searchInput" value="#{sessionScope.searchValue}">
</xp:inputText>
<xp:button value="Search" id="button1" refreshMode="complete" type="submit">
<xp:eventHandler event="onclick" submit="true">
<xp:this.action>
<xe:moveTo targetPage="#searchResult"></xe:moveTo>
</xp:this.action>
</xp:eventHandler>
</xp:button>
</xe:appPage>
What does the runtime error say?
If you can not get to the XPages log files on the server directly, then use XPages Log File Reader from OpenNTF to get easy access to the log files from a browser.
Does it work if you use "searchResult" as the value for targetPage (assuming the appPage is called "searchResult")?
I've now come to a solution with a static line item instead of a button, since I couldn't get the button working. I think it has something to do with the way the single page application handles the access to mobile pages.
The search page looks like this :
<xe:appPage id="appPage34" pageName="searchPage" preload="true" resetContent="true">
<xe:djxmHeading id="djxmHeading34" label="Search..." back="Home" moveTo="home">
</xe:djxmHeading>
<xp:inputText id="searchInput" value="#{sessionScope.searchValue}">
<xp:eventHandler event="onblur" submit="true" refreshMode="complete">
<xp:this.action>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:var svalue = getComponent("searchInput").getValue(); sessionScope.put("searchValue",svalue);}]]></xp:this.script>
</xp:executeScript>
</xp:this.action>
</xp:eventHandler>
</xp:inputText>
<xp:br></xp:br>
<xp:br></xp:br>
<xe:djxmLineItem id="djxmLineItem41" label="Start Search..." moveTo="#searchResult">
</xe:djxmLineItem>
</xe:appPage>
In the mobile page for showing the search result I simply get the value of the sessionScope variable, issue a full text search with the value and use the resulting document collection in a repeat control.
I still would rather use a button because the static line item is not really what a user expects as a gui element to start the search. But at least this is working.