I have a list of products (created using a repeat control) and wish to click on a particular product and bring up a dialog with further information about that particular product. I don't really want to generate dijit.dialog thing for every single product on that page, so how can I do this dynamically possibly using AJAX and partial refresh.
A similar non xpages example can be seen here: http://www.replacementkeys.co.uk/window?dir=asc&limit=12&mode=grid&order=position - where you hover over an image and a quick view button comes up, which then dynamically loads the content for that product.
Any ideas would be truly appreciated.
We build the dialog outside the repeat control and then the action that launches or shows it also sets a viewScope variable that is used UNID for the data source in the dialog. Just make sure you refresh the contents of the dialog as you open it...
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:this.data>
<xp:dominoView var="promptView" viewName="dlgBoxes">
</xp:dominoView>
</xp:this.data>
<xp:panel>
<xp:repeat id="repeat1" rows="30" value="#{promptView}" var="promptEntry">
<xp:panel tagName="div">
<xp:text escape="true" id="computedField1" value="#{promptEntry.dlgName}">
</xp:text>
<xp:button value="details" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:
var pe:NotesViewEntry = promptEntry;
viewScope.put("dlgDocUnid", pe.getUniversalID());
getComponent("dialog1").show();
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:repeat>
</xp:panel>
<xe:dialog id="dialog1" keepComponents="false" partialRefresh="true">
<xe:this.title><![CDATA[#{javascript:
var unid = viewScope.get("dlgDocUnid");
if(!unid) return "";
var doc:NotesDocument = database.getDocumentByUNID(unid);
return doc.getItemValueString("dlgName");}]]></xe:this.title>
<xp:panel>
<xp:this.data>
<xp:dominoDocument var="dlgDoc" formName="dlgBox" action="openDocument">
<xp:this.documentId><![CDATA[#{javascript:viewScope.get("dlgDocUnid");}]]></xp:this.documentId>
</xp:dominoDocument>
</xp:this.data>
<xp:text escape="true" id="computedField2" value="#{dlgDoc.Title}">
</xp:text>
<xp:br></xp:br>
<xp:br></xp:br>
<xp:text escape="true" id="computedField3" value="#{dlgDoc.dlg}">
</xp:text>
</xp:panel>
</xe:dialog>
</xp:view>
Happy coding
/Newbs
You can combine your repeat control with the Extension Library dialog control in order to be able to launch a dialog when the user clicks on the individual row. Chris Toohey has created an excellent article called Popup Dialog Forms from Views in XPages that demonstrates this.
Related
I would to show the tagcloud value individually in each line. Like a list
value1
value2
value3
...
...
..
This is my code. Everytime I choose a value from the list, the display list also got filtered.
This code work in XPNIC without a problem. In the browser I am having the problem as stated above.
<xp:section id="section2" header="Web" type="wide">
<xp:panel>
<xp:this.data>
<xp:dominoView var="view2" viewName="TagCloudActiveCategories" expandLevel="1">
</xp:dominoView>
</xp:this.data>
<xp:repeat id="repeat2" rows="30" value="#{view2}" indexVar="indexVar" var="rowData">
<xe:list id="list2" styleClass="lotusList">
<xp:link escape="true" id="link1" value="/allDocumentsByTag.xsp">
<xp:this.text><![CDATA[# {javascript:rowData.getColumnValues()[0];}]]></xp:this.text>
<xp:this.parameters>
<xp:parameter name="categoryFilter">
<xp:this.value><![CDATA[# {javascript:getComponent("link1").getText();}]]></xp:this.value>
</xp:parameter>
</xp:this.parameters>
<xp:eventHandler event="onclick" submit="true" refreshMode="norefresh"></xp:eventHandler>
</xp:link>
</xe:list>
</xp:repeat>
</xp:panel>
</xp:section>
Any help is very welcome. Thank you in advance.
As far I can see you are using URL parameters to filter your view. This parameter is used by EVERY view datasource on your XPage, even the datasource of your tag cloud.
Add the property ignoreRequestParams=true to your tag cloud view, this should solve the problem.
<xp:this.data>
<xp:dominoView var="view2" viewName="TagCloudActiveCategories" expandLevel="1" ignoreRequestParams="true">
</xp:dominoView>
</xp:this.data>
I have read many of the blog posts on doing a partial refresh on more than one element, but I cannot seem to get it to work.
I made a "toy" example, an Xpage with two fields and one button. Both fields are bound to a sessionScope counter. The button increments the counter and does a partial refresh on the containing panel.
I want to do a partial refresh on the first field, which is not in the panel [in my real Xpage the two fields are very far apart on the form.
Tried many different things to get this to work, but none worked. Is it even possible to do this?
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex"
xmlns:xc="http://www.ibm.com/xsp/custom"
style="background-position:center left"
xmlns:on="http://www.openntf.org/domino/xsp" viewState="nostate"
xmlns:debug="http://www.openntf.org/xsp/debugtoolbar">
First Var<br></br>
<xp:text escape="true" id="computedField1" value="#{sessionScope.number}">
</xp:text>
<br></br>
<xp:br></xp:br>
<br></br>
Second Var<xp:panel id="pnl1">
<xp:text escape="true" id="computedField2" value="#{sessionScope.number}">
</xp:text>
<br></br>
<br></br>
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="pnl1" execMode="partial"
execId="pnl1">
<xp:this.action><![CDATA[#{javascript:var t = sessionScope.number + 1;
sessionScope.number = t;}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:view>
Read Knut's link and got this to work. I made a change to the event handler of the button and it worked. Here is the code:
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="pnl1" execMode="partial"
execId="pnl1">
<xp:this.action><![CDATA[#{javascript:var t = sessionScope.number + 1;
sessionScope.number = t;}]]></xp:this.action>
<xp:this.onComplete><![CDATA[XSP.partialRefreshPost("#{id:computedField1}");]]></xp:this.onComplete>
</xp:eventHandler>
Use XSP.partialRefreshPost(): http://avatar.red-pill.mobi/tim/blog.nsf/d6plinks/TTRY-84B6VP
Why fileDownload1 control becomes editable (delete file attachment icon appears next to fileDownload control) when I just refresh the page. Here is my code where I use a button to refresh the page (just for the example)
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete"></xp:eventHandler>
</xp:button>
<xp:this.data>
<xp:dominoDocument var="document1" formName="myXpage"
databaseName="${javascript:sessionScope.SUPPORT_DB_FILE}"
action="openDocument">
</xp:dominoDocument>
</xp:this.data>
<xp:fileDownload
id="fileDownload1"
rows="30"
displayLastModified="false"
displayType="false"
displayCreated="false"
hideWhen="true"
allowDelete="true"
value="#{document1.MyBodyRTF}">
</xp:fileDownload>
I tried to replicate what you're describing, but am having trouble doing so. I created a new XPage and modeled it after your sample code.
Notable differences:
I never see the trash icon
I had to compute the UNID of some document with an attachment in the appropriate field
I set both the DB name and UNID in beforePageLoad
I noticed an interesting change in the UI behavior (see animated gif below)
I'm not sure what you're running into without having more source code to be able to view, but I can confirm that what I tried doesn't reproduce the result you're describing.
XPage source:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.beforePageLoad><![CDATA[#{javascript:sessionScope.myDbName = database.getFilePath();
var vw:NotesView = database.getView("SomeForms");
var first:NotesDocument = vw.getFirstDocument();
sessionScope.myFirstDoc = first.getUniversalID();
first.recycle();
vw.recycle();}]]></xp:this.beforePageLoad>
<xp:this.data>
<xp:dominoDocument
var="document1"
action="openDocument"
formName="SomeForm"
databaseName="${javascript:return sessionScope.myDbName;}"
documentId="${javascript:return sessionScope.myFirstDoc;}" />
</xp:this.data>
<xp:fileDownload
rows="30"
id="fileDownload1"
displayLastModified="false"
value="#{document1.SomeAttachments}" />
<xp:button
value="Refresh"
id="button1">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="complete" />
</xp:button>
</xp:view>
I have a simple page inside mobile controls. I have an edit box and what I want to happen is to a partial refresh of the current in the onChange event of the edit control. Basically type something in the edit control - hit enter and do the partial refresh.
What's happening is hitting enter if returning the page to the main menu. If I put a value in and hit TAB then it works as I would want.
I'm starting a new app from scratch. But I've done this concept many times with an app in production. I can't find anything special in the code that would "trap" an enter button... So I'm at a loss why I can't get the behavior I want this time around.
Here's a video demo of the problem:
http://traffic.libsyn.com/notesin9/SO-Question2-HB.mp4
Below is the full code.
Thanks for any help!!
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.resources>
<xp:styleSheet href="/.ibmxspres/dojoroot/dijit/themes/tundra/tundra.css">
</xp:styleSheet>
<xp:styleSheet href="/mobile.css"></xp:styleSheet>
</xp:this.resources>
<xe:singlePageApp id="singlePageApp1"
selectedPageName="mainMenu">
<xe:djxmHeading id="djxmHeading1" label="My App"></xe:djxmHeading>
<xe:appPage id="mainMenuID" pageName="mainMenu">
<xe:djxmRoundRectList id="djxmRoundRectList1"
title="Main Menu">
<xe:djxmLineItem id="djxmLineItem9" moveTo="#container"
label="Test Page">
</xe:djxmLineItem>
</xe:djxmRoundRectList>
</xe:appPage>
<xe:appPage id="containerID" pageName="container"
resetContent="true">
<xe:djxmHeading id="djxmHeading5" label="My Page"
back="Main Menu">
</xe:djxmHeading>
<xe:djxmRoundRectList id="djxmRoundRectList2">
<xp:panel id="mainPanel">
<xp:table style="width:100.0%">
<xp:tr>
<xp:td style="width:50%"></xp:td>
<xp:td>Details</xp:td>
</xp:tr>
<xp:tr>
<xp:td>
<xp:inputText id="inputText1" styleClass="target alignVMiddle"
value="#{sessionScope.myValue}">
<xp:this.attrs>
<xp:attr name="autocorrect" value="off"></xp:attr>
<xp:attr name="placeholder" value="Tap to Scan...">
</xp:attr>
</xp:this.attrs>
<xp:eventHandler event="onchange" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:viewScope.put("test", "test");}]]></xp:this.action>
</xp:eventHandler>
</xp:inputText>
</xp:td>
<xp:td></xp:td>
</xp:tr>
</xp:table>
<xp:br></xp:br>
Current Value:
<xp:text escape="true" id="computedField1" value="#{sessionScope.myValue}"></xp:text>
<xp:br></xp:br>
<xp:br></xp:br>
Current Time:
<xp:text escape="true" id="computedField2" value="#{javascript:#Now();}">
<xp:this.converter>
<xp:convertDateTime type="time"></xp:convertDateTime>
</xp:this.converter>
</xp:text>
</xp:panel>
</xe:djxmRoundRectList>
</xe:appPage>
</xe:singlePageApp>
</xp:view>
Can you do something like this to force a partial refresh on Enter?
<xp:inputText id="inputText1" value="#{sessionScope.myValue}">
<xp:eventHandler event="onkeypress" submit="true" refreshMode="partial" refreshId="something">
<xp:this.script><![CDATA[//partial refresh on Enter
if( thisEvent.keyCode === dojo.keys.ENTER ){
dojo.stopEvent( thisEvent );
} else {
return false;
}
]]></xp:this.script>
</xp:eventHandler>
</xp:inputText>
I think the problem is that enter will try to do a submit and submit will return you to the first page. Try to add a check in onkeyup or down for charcode 13 and if this is found return false.
You might also need to do a stopproprigate or something like that.
Google for enter key submit form
From my mobile ;-)
Or perhaps this post. http://tinyurl.com/bsgy9g6
I have an EditBox control in a repeat control. Its iteration formula is:
return 5;
It is successfully displaying 4 edit boxes (the starting index is set to 1).
In SSJS, how can I get the value of the nth Edit Box?
You could set a sessionScope variable (or any scope variable) on the onchange event of the edit box and then in your SSJS reference the sessionScope variable. Here is some sample code, the bottom bit just shows your sessionScope variables on the page.
<?xml version="1.0" encoding="UTF-8"?>
<xp:repeat id="repeat1" rows="30" value="#{javascript:5}"
indexVar="rptIndex">
<xp:inputText id="inputText1">
<xp:eventHandler event="onchange" submit="true" refreshMode="complete">
<xp:this.action>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:sessionScope['text'+rptIndex] = getComponent("inputText1").getValue()}]]></xp:this.script>
</xp:executeScript>
</xp:this.action></xp:eventHandler></xp:inputText>
</xp:repeat>
<xp:table styleClass="debug">
<xp:tr>
<th>Variable Name</th>
<th>Variable Content</th>
</xp:tr>
<xp:repeat id="varRepeat" rows="30" value="#{javascript:sessionScope.keySet();}" var="scopeData">
<xp:tr>
<xp:td>
<xp:text escape="true" id="varName" value="#{javascript:scopeData}" />
</xp:td>
<xp:td>
<xp:text escape="true" id="varValue" value="#{javascript:sessionScope.get(scopeData)}" />
</xp:td>
</xp:tr>
</xp:repeat>
</xp:table>
</xp:view>
When you add a submission to an onChange event you create a rather chatty application - might bite you. The solution for setting the focus is rather different. First: focus is a client side operation, so you need a client script that 'knows what control is the first failure. The good news: XPages adds to all fields that failed a server side validation the attribute aria-invalid=true.
So you can use a dojo.onLoad script that queries that and sets the focus to the first member of the result. See also http://dontpanic82.blogspot.com/2011/07/xpages-styling-invalid-field.html
And for the query syntax:
http://dojotoolkit.org/reference-guide/1.7/dojo/query.html
Repeats are fun to deal with to say the least. If you look at examples in the teamroom template mobileThread custom control you'll see a repeat for displaying a list of replies, you'll also notice a lot of javascript to go along with it as for example running script on one button click would run on all buttons in the repeat.
If you are looking for the validation problem stwissel's solution looks the best. If this is something else and at some point you just need the value of any given edit box, maybe you should think about something like:
var domEl = dojo.byId(' <repeatControlId> ');
var textBoxes = domEl.getElementsByTagName("input");
var certainValue = textBoxes[3].value;
Now certainValue contains the value of a given edit box.
haven't tried this out, might need a little tweaking but the general idea should work I would think.
added another comment so i could add code.
Did a quick test and works fine for me, see my example below. Hope it helps. Try adding some print outs to see is it getting each bit.
<xp:repeat id="TestRepeat" rows="100" var="rowData"
indexVar="commentIndex" first="0" rendered="true">
<xp:this.value><![CDATA[#{javascript:
var dataArray = new Array();
dataArray.push(" Test");
dataArray.push(" Test");
dataArray.push(" Test");
dataArray.push(" Test");
dataArray.push(" Test");
return dataArray;
}]]></xp:this.value>
<xp:panel>
<xp:label value="Test"></xp:label>
<xp:inputText id="inputText1" value="Test" defaultValue="Test">
</xp:inputText>
<xp:br></xp:br>
</xp:panel>
</xp:repeat>
<xp:button value="Test" id="button1">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script>
<xp:executeClientScript>
<xp:this.script><![CDATA[
var domEl = dojo.byId('#{id:TestRepeat}');
var textBoxes = domEl.getElementsByTagName("input");
alert( "Value 1: " + textBoxes[0].value);
]]></xp:this.script>
</xp:executeClientScript>
</xp:this.script>
</xp:eventHandler>
</xp:button>