Xpages-Setting Up the ViewScope from client-side javaScript (oncontextmenu) - xpages

I have a Xpages in which I have repeat control, Now I have the list of documents from a view. Onclick on the row is setting the viewScope Array with the Unid.
I have done this actually for the purpose of selecting the document and to keep track that which document is selected, I am successfull in doing that but the main purpose was, I wanted to obtain the UNID on right-Click context menu.
Now, Also the right click event is providing me the UNID in one text field. I have obtained this by using "oncontextmenu" attribute in a div tag.
<div oncontextmenu="javascript:
var a = document.getElementById('#{id:inputText1}').value;
document.getElementById('#{id:inputText2}').value=a;
return false;">
There is "inputText1" in each row with the default value UNID of the perticular row.
In above code I am getting the UNID from "inputText1" and setting it up to the "inputText2", So on right click I am successfully getting the UNID of the clicked row.
In futher case I have an idea that I can do any operation by using that UNID but instead of setting the UNID to the "inputText2", I want to set this UNID to viewScope not in "inputText2".
Basically my overall issue is that I want to set UNID which I am getting on right-click(oncontextmenu) to viewScope not in any text field("inputText2") using above client-side java script.
example code:
<?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">
<xp:this.afterPageLoad><![CDATA[#{javascript:var myList = new java.util.ArrayList();
sessionScope.put("myList",myList);}]]></xp:this.afterPageLoad>
<xp:button value="Refresh" id="button3">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="repeat2">
</xp:eventHandler></xp:button>
<xp:repeat id="repeat2" rows="30" value="#{sessionScope.myList}"
var="listData">
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript:listData+" , "}]]></xp:this.value>
</xp:text>
</xp:repeat>
<xp:inputText id="inputText2"></xp:inputText>
<xp:repeat id="repeat1" rows="30" var="rowData"
indexVar="repeatIndex" first="0" styleClass="abc">
<xp:this.value><![CDATA[#{javascript:var viewName = "Adressakten";
var v:NotesView = database.getView(viewName);
return v.getAllEntries();}]]></xp:this.value>
<xp:br></xp:br>
<div oncontextmenu="javascript:
var a = document.getElementById('#{id:inputText1}').value;
document.getElementById('#{id:inputText2}').value=a;
return false;">
<xp:inputHidden id="inputText1">
<xp:this.defaultValue><![CDATA[#{javascript:var doc:NotesDocument = rowData.getDocument();
return doc.getUniversalID();}]]></xp:this.defaultValue>
</xp:inputHidden>
<xp:div id="div1">
<xp:this.style><![CDATA[#{javascript:javascript:var keyCode = rowData.getDocument().getUniversalID();
var myArray = sessionScope.get("myList");
if(myArray.contains(keyCode))
return "border-color:rgb(192,192,192);border-style:solid;border-width:thin;height:42.0px;background-color:green;cursor:pointer;"
else
return "border-color:rgb(192,192,192);border-style:solid;border-width:thin;height:42.0px;background-color:rgb(255,255,128);cursor:pointer;"}]]></xp:this.style>
<xp:text escape="true" id="computedField2">
<xp:this.value><![CDATA[#{javascript:var doc:NotesDocument = rowData.getDocument();
return doc.getItemValueString('aTitel');}]]></xp:this.value>
</xp:text>
<br />
document Id:
<xp:text escape="true" id="computedField3">
<xp:this.value><![CDATA[#{javascript:var doc:NotesDocument = rowData.getDocument();
return doc.getUniversalID();}]]></xp:this.value>
</xp:text>
<xp:br></xp:br>
<xp:button value="Add" id="button1" rendered="false">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="computedField2">
<xp:this.action><![CDATA[#{javascript:var keyCode = rowData.getDocument().getUniversalID();
var myArray = sessionScope.get("myList");
if(!myArray.contains(keyCode)){
myArray.add(keyCode);
}}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button value="Remove" id="button2" rendered="false">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:var keyCode = rowData.getDocument().getUniversalID();
var myArray = sessionScope.get("myList");
myArray.remove(keyCode)}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:var keyCode = rowData.getDocument().getUniversalID();
var myArray = sessionScope.get("myList");
if(!myArray.contains(keyCode)){
myArray.add(keyCode);
}
else{
myArray.remove(keyCode);
}}]]></xp:this.action>
</xp:eventHandler>
</xp:div></div>
<br />
</xp:repeat>
</xp:view>

It sounds like the JSON RPC Service from the Extension Library is what you need. That will allow you to run SSJS using a value passed from CSJS. It's covered on pages 351-3 of XPages Extension Library book and there may be examples in Extension Library Demo database.

I absolutely agree with the answer of Paul Stephen Withers, the best way to do this is using JSON RPC.
Here a JSON RPC working example:
<?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">
<xe:jsonRpcService id="jsonRpcService1" serviceName="rpcService">
<xe:this.methods>
<xe:remoteMethod name="setUniqueID" script="sessionScope.put('sessionScopeVarTest', unid);">
<xe:this.arguments>
<xe:remoteMethodArg name="unid" type="string"></xe:remoteMethodArg>
</xe:this.arguments>
</xe:remoteMethod>
</xe:this.methods>
</xe:jsonRpcService>
Show Value of "sessionScope.sessionScopeVarTest" ->
<xp:text escape="true" value="#{sessionScope.sessionScopeVarTest}" style="font-weight:bold">
</xp:text>
<br/>
<br/>
<xp:button id="btnTriggerRPC" value="Trigger RPC Method">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[rpcService.setUniqueID('13F51C65D8C257FCC1257ED000361786')]]></xp:this.script>
</xp:eventHandler>
</xp:button>
<xp:button id="btnRefresh" value="Refresh Page">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
</xp:eventHandler>
</xp:button>
</xp:view>

Related

using viewscope for repeat var does not update viewscope outside the repeat

This gets me every time.
I want to edit the viewScope components and then use the results elsewhere - but in this simple example the computed field does not update .... what is the best way to do this?
Thanks
<xp:this.beforePageLoad><![CDATA[#{javascript:viewScope.Test = [];
viewScope.Test.push("Hello");
viewScope.Test.push("Go");
viewScope.Test.push("Hello1");}]]></xp:this.beforePageLoad>
<xp:repeat id="repeat1" rows="30" value="#{viewScope.Test}"
var="row" indexVar="i">
<xp:inputText id="inputText1" value="#{row}">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="computedField1"></xp:eventHandler>
</xp:inputText>
</xp:repeat>
This is new data
<xp:text escape="true" id="computedField1"
value="#{viewScope.Test}">
</xp:text>
Fixed it by changing the value of inputText to "#{viewScope.Test[i]}"
<xp:this.beforePageLoad><![CDATA[#{javascript:
viewScope.Test = ["Test","Test1","Test2"];
}]]></xp:this.beforePageLoad>
<xp:repeat id="repeat1" rows="30" value="#{viewScope.Test}"
var="row" indexVar="i">
<xp:inputText id="inputText2" value="#{viewScope.Test[i]}">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="computedField1">
</xp:eventHandler></xp:inputText>
</xp:repeat>
<xp:br></xp:br>This is new data
<xp:text escape="true" id="computedField1" value="#{viewScope.Test}"></xp:text>

How to do a partial refresh of multiple items in Xpages correctly

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

Xpages: Refresh read only field on competition of DialogBox

My Xpage is in read mode. There is a Notes field with a "Add Notes" button. Click the button, user adds notes in dialogbox and clicks "Add Notes". The button does the work of adding the notes and saving the document.
I want to update the underlying notes field so the user will see their additions. How can I accomplish 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">
<xp:panel id="pnlAll">
<xp:this.data>
<xe:objectData saveObject="#{javascript:PCModel.save()}"
var="PCModel">
<xe:this.createObject><![CDATA[#{javascript:var pc = new com.scoular.model.PC();
var unid = sessionScope.get("key");
if (unid != null) {
pc.loadByUnid(unid);
sessionScope.put("key","");
viewScope.put("readOnly","Yes");
} else {
pc.create();
viewScope.put("readOnly","No");
}
viewScope.status = pc.status;
return pc;}]]></xe:this.createObject>
</xe:objectData>
</xp:this.data>
<xp:inputTextarea id="inputTextarea3" cols="1" rows="10"
disabled="true" value="#{PCModel.notes}">
</xp:inputTextarea>
<xp:br></xp:br>
<xp:button value="Add Notes" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:getComponent("dialogAddNotes").show()}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:br></xp:br>
<xp:div styleClass="modal fade" id="model1" role="dialog">
<xe:dialog id="dialogAddNotes" styleClass="modal-dialog"
title="Add Notes">
<xp:div style="margin-left:10.0px;margin-right:10.0px">
<xp:inputTextarea id="inputTextarea4" value="#{viewScope.addNotes}"
cols="1" rows="18">
</xp:inputTextarea>
</xp:div>
<xp:div styleClass="modal-footer">
<xp:button type="button" styleClass="btn btn-primary" id="button17"
value="Add Notes">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="dialogAddNotes">
<xp:this.action><![CDATA[#{javascript:var newLne = "\n";
var oldNte = PCModel.notes;
var usrNme:String = userBean.displayName;
var dte = session.createDateTime(#Now());
var lnkStr:String = "Notes added by " + usrNme + " at " + dte + newLne + newLne + viewScope.addNotes + newLne + newLne + oldNte;
var newNotes:String = lnkStr
PCModel.notes = newNotes;
PCModel.save();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:div>
</xe:dialog>
</xp:div>
</xp:panel>
</xp:view>
You need to partially refresh the updated text area field called inputTextarea3 instead of the dialog.

Use XSP.partialRefreshPost function in XPages Extension Library dialog

In a xe:dialog (XPages Extension Library dialog), I want to use XSP.partialRefreshPost function, but when refreshing the entered values are lost.
The following example demonstrate the problem.
ComboBox1, inputText1, ComboBox2, inputText2 : OK but not in a xe:dialog
ComboBox3, inputText3 : OK but not use XSP.partialRefreshPost
ComboBox4, inputText4 : NOK because it uses XSP.partialRefreshPost function in xe:dialog
I try to change the properties xe:dialog without success.
How to use XSP.partialRefreshPost in a xe:dialog to have refresh OK ?
Thanks
<?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">
<xp:label id="label1" value="refresh partial"></xp:label>
<xp:comboBox id="comboBox1">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:return ["1", "2", "3"];}]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="true" refreshMode="partial"refreshId="comboBox1">
</xp:eventHandler>
</xp:comboBox>
<xp:inputText id="inputText1">
<xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="inputText1">
</xp:eventHandler>
</xp:inputText>
<xp:br></xp:br>
<xp:label id="label2" value="refresh XSP.partialRefreshPost"></xp:label>
<xp:comboBox id="comboBox2">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:return ["1", "2", "3"];}]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="false">
<xp:this.script><![CDATA[XSP.partialRefreshPost("#{id:comboBox2}", {immediate: true});]]></xp:this.script>
</xp:eventHandler>
</xp:comboBox>
<xp:inputText id="inputText2">
<xp:eventHandler event="onchange" submit="false">
<xp:this.script><![CDATA[XSP.partialRefreshPost("#{id:inputText2}", {immediate: true});]]></xp:this.script>
</xp:eventHandler>
</xp:inputText>
<xp:br></xp:br>
<xe:dialog id="dialog1" partialRefresh="true">
<xp:label id="label3" value="refresh partial"></xp:label>
<xp:comboBox id="comboBox3">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:return ["1", "2", "3"];}]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="comboBox3">
</xp:eventHandler>
</xp:comboBox>
<xp:inputText id="inputText3">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="inputText3">
</xp:eventHandler>
</xp:inputText>
<xp:br></xp:br>
<xp:label id="label4" value="refresh XSP.partialRefreshPost"></xp:label>
<xp:comboBox id="comboBox4">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:return ["1", "2", "3"];}]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="false">
<xp:this.script><![CDATA[XSP.partialRefreshPost("#{id:comboBox4}", {immediate: true});]]></xp:this.script>
</xp:eventHandler>
</xp:comboBox>
<xp:inputText id="inputText4">
<xp:eventHandler event="onchange" submit="false">
<xp:this.script><![CDATA[XSP.partialRefreshPost("#{id:inputText4}", {immediate: true});]]></xp:this.script>
</xp:eventHandler>
</xp:inputText>
</xe:dialog>
<xp:button id="button1" value="dialog">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[XSP.openDialog('#{id:dialog1}');]]></xp:this.script>
</xp:eventHandler>
</xp:button>
</xp:view>
partialRefreshPost doesn't work as expected in <xe:dialog>, e.g., when you choose a value in a combobox then partialRefreshPost sends the selected value on change event to server but server's response contains the old value and combobox value jumps back to old value. Even binding the field to data like a scope variable doesn't help.
But there is a workaround. Add parameter execId to partialRefreshPost:
XSP.partialRefreshPost("#{id:comboBox4}",
{execId: "#{id:comboBox4}", immediate: true})
Specify the element which you want to refresh, in this case the same (comboBox4). This way it will work as expected - like outside of a dialog box.

How to Save Values in Documents Edited In-line On Repeat Control

I have a repeat control on an xPage with a text field displayed directly in edit mode. When a user changes the value in the field, I need them to be able to either:
Select an icon directly beside the field to save the value in the document.
Make changes to this field in more than one document and click a button to save all of these changes to the appropriate documents saved simultaneously.
What I have so far is a method of capturing the unids of the documents whose editable field has been updated.
I cannot get either of these saves to work. I have listed below the portion of the code that controls these areas.
Here's the save all and sessionScope information
<xp:panel id="InlineEditContainer" xp:key="facetMiddle" style="width:100%">
<xp:this.data>
<xp:dominoView var="view1" viewName="vwMetricsByAssigned">
<xp:this.postOpenView><![CDATA[#{javascript:var myList = new java.util.ArrayList();
sessionScope.put("myList", myList);}]]></xp:this.postOpenView></xp:dominoView>
</xp:this.data>
<xp:button value="Submit All" id="button1">
<xp:eventHandler event= <"onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:// Getting list of unids from docs which have been updated, and saving those docs
var db:NotesDatabase
if(sessionScope.myList == null){
return;
}else{
for (var s in sessionScope.myList){
var doc:NotesDocument = (db ? db.getDocumentByUNID(s) : database.getDocumentByUNID(s));
if (doc && doc.isValid()) {
doc.save();
}
}
}}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:br></xp:br>
<xp:repeat id="repeat1" rows="30" value="#{sessionScope.myList}" var="listData">
<xp:text escape="true" id="computedField6"><xp:this.value><![CDATA[#{javascript:listData + " , "}]]></xp:this.value></xp:text></xp:repeat>
<xp:br></xp:br>
Here's all the repeat data
<xp:repeat id="repeat2" rows="20" var="FColl" indexVar="idx" value="#{javascript:view1}">
<xp:panel id="InlineEditContainer2">
<xp:this.data>
<xp:dominoDocument var="document1" formName="frmMetricData" action="editDocument" documentId="# {javascript:FColl.getNoteID();}" >
</xp:dominoDocument>
</xp:this.data>
<xp:tr>
<xp:td id="td1">
<xp:text escape="true" id="computedField3">
<xp:this.value> <![CDATA[#javascript:FColl.getDocument().getItemValueString("BusinessUnit")}]]>
</xp:this.value>
</xp:text>
</xp:td>
<xp:td id="td2">
<xp:link escape="true" id="link1" value="/MetricData.xsp">
<xp:this.text><![CDATA[#{javascript:FColl.getDocument().getItemValueString("MetricName")}]]> </xp:this.text>
<xp:eventHandler event="onclick" submit="true" refreshMode="norefresh" immediate="true">
<xp:this.action>
<xp:openPage name="/MetricData.xsp" target="editDocument" documentId="#{javascript:return FColl.getNoteID();}" />
</xp:this.action></xp:eventHandler>
</xp:link>
</xp:td>
<xp:td id="td3">
<xp:inputText id="EditBox3" value="#{document1.Actual}" tabindex="1">
<xp:this.defaultValue><![CDATA[# {javascript:FColl.getDocument().getItemValueString("Actual")}]]></xp:this.defaultValue>
<xp:this.converter>
<xp:convertNumber type="number" integerOnly="true" />
</xp:this.converter>
<xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="repeat1">
<xp:this.action><![CDATA[#{javascript:// get the universalID of the document
var keyCode = FColl.getDocument().getUniversalID();
// Create an Array
var myArray = sessionScope.get("myList");
//If it's not already in the Array then add it.
if (!myArray.contains(keyCode)) {
myArray.add(keyCode);
}}]]></xp:this.action>
</xp:eventHandler></xp:inputText>
<xp:span>
<xp:image url="/.ibmxspres/domino/oneuiv2/images/iconConfirmation16.png" id="image1">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action>
<xp:saveDocument var="document1" />
</xp:this.action>
</xp:eventHandler>
</xp:image>
</xp:span>
If anybody can give me any ideas to try, I would be very grateful.
Make it simple! There is a simple action "save". Comes in save and save all flavors. The later goes below the repeat and saves any changed document.

Resources