Xpages repeat control division by zero - xpages

I'm using a repeat control displaying names. The content is displayed proberly, but I needed a pager because there can be more than 30 entries.
As soon as I add a pager for this repeat control and press a button doing a partial refresh on the site I get a "division by zero" error.
Here's my repeat control:
<xp:repeat id="repeat1" rows="30" var="namesList" repeatControls="true" indexVar="rowIndex">
<xp:table>
<xp:tr>
<xp:td>
<xp:link escape="true" id="Employee">
<xp:this.text><![CDATA[#{javascript:namesList.getItemValueString("Employee")}]]></xp:this.text></xp:link>
</xp:td>
</xp:tr>
</xp:table>
<xp:this.value><![CDATA[#{javascript:try {
var wfDoc:NotesDocument = docApplication.getDocument(true);
var dcNoAnswer:NotesDocumentCollection = database.createDocumentCollection();
var count:Integer = 0;
//Gets all response documents, but only adds those to the document collection, without a valid
//response to the cycle
if (wfDoc.getResponses() != null) {
var dc:NotesDocumentCollection = wfDoc.getResponses();
var doc:NotesDocument = dc.getFirstDocument();
while (doc != null) {
if (doc.getItemValueString("Response") == "") {
dcNoAnswer.addDocument(doc);
}
doc = dc.getNextDocument();
}
dc.recycle();
}
docApplication.replaceItemValue("MissingResponsesCount", dcNoAnswer.getCount());
wfDoc.recycle();
return dcNoAnswer;
} catch(e) {
dBar.error("Show no response repeat control data: " + e);
}}]]></xp:this.value>
</xp:repeat>
And here's my pager:
<xp:pager layout="Previous Group Next" id="pager3" for="repeat1"></xp:pager>
As I said, doing a partial refresh on the site oder panel, I'll get this error:
I've been looking for an error for some time, but I can't see anything wrong here. Did anybody else have such a problem and maybe has a solution?

You have repeatControls="true" set. That means "create the controls once and never again", so you can't use a pager to navigate, as mentioned here. Remove repeatControls="true" and it will work.
If you look at the stack trace, it will fail on getStart().

Try adding alwaysCalculateLast="false" to your pager. The repeat control could have 0 values (because of dcNoAnswer) and maybe you have set xsp.repeat.allowZeroRowsPerPage=true in your xsp properties settings.

Related

xpages: how to make the edit box read-only and still have the session scope variable?

I have a xpage that contains 4 edit boxes and a button, they are used to export the data in excel. I use session scope in those four edit boxes because I have store the value in order to generate the excel.
The design look looks like the following:
//1st edit box: get the user name, set it to default so the user does not need to type his/her name
<xp:inputText id="inputText1" value="#{sessionScope.User}">
<xp:this.defaultValue><![CDATA[#{javascript: #Name("[CN]",#UserName())}]]></xp:this.defaultValue>
</xp:inputText>
//2nd edit box: after get the user name in edit box 1, retrieve the user's department in this edit box
<xp:inputText id="inputText2"value="#{sessionScope.Department}">
<xp:this.defaultValue><![CDATA[#{javascript:#DbLookup(#DbName(),"UserView", (getComponent("inputText1").getValue()),2 )}]]></xp:this.defaultValue>
</xp:inputText>
//3rd edit box: get the start search date in YYYYMM format, user only can type numbers
<xp:inputText id="inputText3" value="#{sessionScope.startYYYYMM}">
<xp:eventHandler event="onkeypress" submit="false">
<xp:this.script><![CDATA[if (event.keyCode >= 48 && event.keyCode <= 57)
{
event.returnValue = true;
}
else
{
event.returnValue = false;
}]]></xp:this.script>
<xp:this.parameters>
<xp:parameter name="message1" value="value">
/xp:parameter>
</xp:this.parameters>
</xp:eventHandler>
</xp:inputText>
//4th editbox: get the endsearch date in YYYYMM format, user only can type numbers
<xp:inputText id="inputText4" value="#{sessionScope.startYYYYMM}">
<xp:eventHandler event="onkeypress" submit="false">
<xp:this.script><![CDATA[if (event.keyCode >= 48 && event.keyCode <= 57)
{
event.returnValue = true;
}
else
{
event.returnValue = false;
}]]></xp:this.script>
<xp:this.parameters>
<xp:parameter name="message1" value="value">
/xp:parameter>
</xp:this.parameters>
</xp:eventHandler>
</xp:inputText>
//a button to call another page to export the excel
<xp:button value="Export" id="button11">
<xp:eventHandler event="onclick" submit="true" immediate="false" save="false" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:context.redirectToPage("ExportExcel.xsp");}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
I run the code, it works fine. However here is what I would like to ask. In the first and the second edit box, if I set those edit boxes to Read-only. It seems lose the session scope variable and I run the code, the excel just contains the default header.
I find this post ReadOnly field in Xpage not submitted is very similar to my case, so I set the edit box to editable and try to apply this code from the post:
//for 1st editbox
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[function makeFieldReadOnly() {
document.getElementById("#{id:inputText1}").readOnly = true;
}
window.onload = makeFieldReadOnly;]]></xp:this.value>
</xp:scriptBlock>
//for 2nd edit box
<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[function makeFieldReadOnly() {
document.getElementById("#{id:inputText2}").readOnly = true;
}
window.onload = makeFieldReadOnly;]]></xp:this.value>
</xp:scriptBlock>
The edit box still editable and the excel is not work properly (only display the default header).
So how can I make the edit box read-only and still have the session scope variable?
Grateful for your advice please. Thank you.
Reference:
ReadOnly field in Xpage not submitted
export data from panel
You can calculate the values for your two sessionScope variables in e.g. the beforeRenderResponse:
<xp:this.beforeRenderResponse><![CDATA[#{javascript:
sessionScope.User = #Name("[CN]",#UserName());
sessionScope.Department = #DbLookup(#DbName(),"UserView", (#Name("[CN]",#UserName()),2 )
}]]></xp:this.beforeRenderResponse>
You can then show the values of the sessionScope variables in computed text fields instead of input fields:
<xp:text escape="true" id="computedField1" value="#{sessionScope.User}" />
<xp:text escape="true" id="computedField2" value="#{sessionScope.Department}" />
I had this issue with 9.01 FP6
The best solution was to place the inputs in a xp:panel and then use the readonly attribute on the panel to make the field within it read only.
This worked well and was easy to implement

Is it possible to assign value depends on the multiline edit box value

Update: code reduced and further description about this web application that I am trying to do.
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript: sessionScope.DishNameValue;
}]]></xp:this.value>
</xp:text>
<xp:br></xp:br>
<xp:br></xp:br>
 <xp:table style="width:636.0px">
<xp:tr>
<xp:td style="width:250.0px">
<xp:inputTextarea id="inputTextarea2">
<xp:this.value><![CDATA[#{javascript:
var selectedDishNameRestaurant = #DbLookup(#DbName(),"RestaurantDishNameView", (getComponent("computedField1").getValue()),3)
if(selectedDishNameRestaurant != null)
{
return selectedDishNameRestaurant;
}
else
{
return "nothing here"
}
}]]></xp:this.value>
<xp:this.multipleSeparator><![CDATA[#{javascript:"\n"}]]></xp:this.multipleSeparator>
<xp:this.rendered><![CDATA[#{javascript:if(getComponent("computedField1").getValue() != null)
{
return true;
}}]]></xp:this.rendered>
</xp:inputTextarea>
</xp:td>
<xp:td style="width:250.0px">
<xp:inputTextarea id="inputTextarea4">
<xp:this.value><![CDATA[#{javascript:var selectedDishNameRestaurant = #DbLookup(#DbName(),"RestaurantDishNameView", (getComponent("computedField1").getValue()),3)
var createdDishValue = #DbLookup(#DbName(),"CreatedDishView", selectedDishNameRestaurant,2);
var restaurantDishValue = #DbLookup(#DbName(),"RestaruantDishView", createdDishValue,1);
if(creatededDishValue !=null){
return "Yes";
}
else
{
return "No";
}
}]]></xp:this.value>
<xp:this.multipleSeparator><![CDATA[#{javascript:"\n"}]]></xp:this.multipleSeparator>
<xp:this.rendered><![CDATA[#{javascript:if(getComponent("computedField1").getValue() != null)
{
return true;
}}]]></xp:this.rendered>
</xp:inputTextarea>
</xp:td>
<xp:td style="width:250.0px">
<xp:inputTextarea id="inputTextarea6">
<xp:this.value><![CDATA[#{javascript:var selectedDishNameRestaurant = #DbLookup(#DbName(),"RestaurantDishNameView", (getComponent("computedField1").getValue()),3)
var createdDishValue = #DbLookup(#DbName(),"CreatedDishView", selectedDishNameRestaurant,2);
var restaurantDishValue = #DbLookup(#DbName(),"RestaruantDishView", createdDishValue,1);
var createdDate = #DbLookup(#DbName(),"RestaruantDishView", createdDishValue,2);
if(createdDishValue !=null){
return createdDate;
}
else
{
return "";
}
}]]></xp:this.value>
<xp:this.multipleSeparator><![CDATA[#{javascript:"\n"}]]></xp:this.multipleSeparator>
<xp:this.rendered><![CDATA[#{javascript:if(getComponent("computedField1").getValue() != null)
{
return true;
}}]]></xp:this.rendered>
</xp:inputTextarea>
</xp:td>
</xp:tr>
</xp:table>
In the first page:
The user will select the dish name or style (use radio button group and combo box) for the display it in the second page. (This part works fine)
In the second page:
There will be a computed field to display the selected value.(This part works fine because I use session variable to store the value)
There is a multi line edit box, it will display values in separate lines depends on the computed field's value. For example if the user select the dish name, then it will display which restaurant(s) has this dish. In this part, I use #DbLookup to achieve at this stage, the program still works fine).
There is another multi line edit box. it display values depends on the first multi line edit box. For example, the first multi line edit box can display a list of restaurants that has the specific dish name(selected by the user). The second multi line edit box will display the value that whether the restaurant has created the dish or not, if the the restaurant created the dish, the value return "Yes", otherwise return "No".
In this part, no matter how many values in the first multi line edit box, I could only get one "Yes" or one "No" in the second multi line edit box.
Would someone let me know how to make the second multi line edit box to display all values please? Thank you.
I tried to use for loop but not work.
for (i = getComponent("inputTextarea2").getValue(); i < getComponent("inputTextarea2").length; i++)
Disclaimer: I prefer the following information should be a comment but I don't have enough rights to do that.
Here is my thought the reason why you only have one "Yes" or "No" for the result is in this part: (if my concept is wrong, please correct me)
if(creatededDishValue !=null){
return "Yes";
}
else
{
return "No";
}
Because createdDishValue is not null, it will return "Yes", so if the #DbLookup calculation is correct, it will lookup a value. So if there are 10 values, the result will only display 1 "Yes" or 1 "No". Therefore, if you need to return 10 Yes/No, you need to do some programming to achieve that.
Please note: I haven't try your for loop code yet but I would recommend you to have a look at this website:
JavaScript for...in loop
According to the website, it mentioned
The for...in loop is used to loop through an object's properties.
So how about try to use for in loop instead of for loop in your code?
Thank you.

XPages: image onCclick needs 2 clicks to do what is expected

I have a custom control that contains 2 images: add and remove from favorites.
There is some code on the onCLick event of the image, and both images use a SSJS function to see if the current document is already in the favorites or not, in the visible property of each image.
All works well, execpt that I need to click twice on the image in order to see the changes in the UI. Both onClick events are set to FullUpdate (also tried partial update with the panel that contains the images).
I could move all the favorites logic into session scope variables, but I think this should work as is. I just don't understand why I need to click twice, as if the partial refresh doesn't do anything (though it is, as I see the reload Arrow in the browser!).
Can it be that the code takes too long to execute and the refresh doesn'T get the updated info???
Here's the custom control 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.resources>
<xp:script src="/AppUtils.jss" clientSide="false"></xp:script>
</xp:this.resources>
<xp:image url="/favorites-add.png" id="image1"
alt="Add to Favorites" title="Add to Favorites">
<xp:this.rendered><![CDATA[#{javascript:!isInFavorites(document1.getDocument().getUniversalID(), userBean.canonicalName);
}]]></xp:this.rendered>
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:addToFavorites(document1.getDocument().getUniversalID(),userBean.canonicalName);}]]></xp:this.action>
</xp:eventHandler>
</xp:image>
<xp:image url="/favorites-remove.png" id="image2"
alt="Remove from Favorites" title="Remove from Favorites">
<xp:this.rendered><![CDATA[#{javascript:isInFavorites(document1.getDocument().getUniversalID(),userBean.canonicalName);
}]]></xp:this.rendered>
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:removeFromFavorites(document1.getDocument().getUniversalID(),userBean.canonicalName);}]]></xp:this.action>
</xp:eventHandler>
</xp:image>
</xp:view>
And here's the SSJS:
function addToFavorites(unid, userName) {
var newDoc:NotesDocument = database.createDocument();
newDoc.appendItemValue("Form","Favorite");
newDoc.appendItemValue("UserName", userName);
newDoc.appendItemValue("DocUNID", unid);
newDoc.save();
return;
}
function removeFromFavorites(unid, userName) {
var notesView:NotesView = database.getView("(lkpFavorites)");
var keys = new java.util.Vector();
keys.addElement(userName);
keys.addElement(unid);
var coll:NotesDocumentCollection = notesView.getAllDocumentsByKey(keys, true);
if(coll.getCount()==1) {
coll.getFirstDocument().remove(true);
}
return;
}
function isInFavorites(unid, userName) {
var notesView:NotesView = database.getView("(lkpFavorites)");
var keys = new java.util.Vector();
keys.addElement(userName);
keys.addElement(unid);
var coll:NotesDocumentCollection = notesView.getAllDocumentsByKey(keys, true);
if(coll.getCount()>0) {
return true;
} else {
return false;
}
}
I'd suggest you to put an xp:link around your image to cast the event code instead of using the evennts of the image directly.
OK, not sure what happened there but I manually edited the custom control's source to see wheter I had empty eventHandler as suggested by Oliver, and it started to work as expected. I am totally unsure of what I changed: to my knowledge, all I did was to add extra "returns" in the source view, to make it more readable... Christmas gift I guess.
All is good now. Thanks to all :)

xpages get UNID for a document/datasource

I'm using Mark Hughes picklist on my xpage which is using a datasource. The view from which I pick the values is listing documents having another datasource.
I put the selected value into an <xp:inputText>. I do want to create a link which should redirect me to the listed document from the view ( from it I took the value ). In other words, I do want to find out the UNID of the document from the view, which I did selected it.
I tried the following code for the ssjsSelectFunction:
var unid = viewScope.unid;
if(typeof unid != "undefined" && unid != null)
{
var doc = database.getDocumentByUNID(unid);
var val1 = doc.getItemValueString("txt_numeAcord_1");
var val2 = doc.getUniversalID();
getComponent("inputText24").setValue(val1);
getComponent("inputText25").setValue(val2);
}
But after selecting the desired doc. from the picklist, only inputText25 is updated with the value ( UNID ), the inputText24 is empty. Only if I open again the picklist and select the doc., the inputText24 field value is added. I guess I'm missing something.
How can I achieve this?
My xpage code:
<?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" >
<xp:this.data>
<xp:dominoDocument var="Contr" formName="(fmFormularCIP)"></xp:dominoDocument>
<xp:dominoView var="view1" viewName="vwAcord"></xp:dominoView>
</xp:this.data>
<xp:panel id="AcordCadru">
   
<xp:br></xp:br>
  
<xp:checkBox text="Acord cadru" id="checkBox6"checkedValue="Da" uncheckedValue="Nu" value="#{Contr.chkAcord}">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="AcordCadru">
</xp:eventHandler>
</xp:checkBox>
 
<xp:inputText id="inputText24" value="#{Contr.acord}">
</xp:inputText>
<xc:viewpicklist rowsPerPage="10"
buttonImage="./folder_explore.png" tableClass="tablecellgreen"
headerClass="headerclass" rowClass="odd, even" searchBar="false"
searchButtonText="Search" searchButtonClass="button2"
searchBarClass="headerclass" pagerStyleFirst="navbutton1"
pagerStylePrevious="navbutton2" pagerStyleCurrent="navbutton4"
pagerStyleNext="navbutton2" pagerStyleLast="navbutton3"
typeAheadBar="false" select="UNID" onReturn="Set Scope Value"
bottomBarClass="bottomround headerclass" cancelButtonText="Cancel"
cancelButtonClass="button2 floatthisright" type="Single Value"
finishButtonText="Finish" finishButtonClass="button2 floatthisright"
multiSelectButtonAddImg="./add.png"
multiSelectButtonRemoveImg="./delete.png"
picklistButtonClass="button" openDialogWith="Button"
picklistLinkImg="./add.png" multiSelectLinkAddImg="./add.png"
multiSelectLinkRemoveImg="./delete.png" selectWith="Button"
multiValueSeparator="," clearSearchImg="./cross.png"
SelectCellWidth="30px" dialogID="dialog1"
dialogTitle="Alegeti nr. acord cadru" fieldName="inputText24"
refreshID="AcordCadru" datasrc="view1" selectColumn="0"
varName="viewScope.unid">
<xc:this.viewColumn>
<xp:value>0</xp:value>
<xp:value>1</xp:value>
<xp:value>2</xp:value>
<xp:value>3</xp:value>
<xp:value>4</xp:value>
</xc:this.viewColumn>
<xc:this.ssjsSelectFunction><![CDATA[#{javascript:
var unid = viewScope.unid;
if(typeof unid != "undefined" && unid != null)
{
var doc = database.getDocumentByUNID(unid);
var val1 = doc.getItemValueString("txt_numeAcord_1");
var val2 = doc.getUniversalID();
Contr.setValue("acord",val1);
Contr.setValue("sv",val2);
}}]]></xc:this.ssjsSelectFunction>
</xc:viewpicklist>
<xp:br></xp:br>
   
<xp:inputText id="inputText25" value="#{Contr.sv}">
</xp:inputText>
</xp:panel>
</xp:view>
inputText24 doesn't get the selected value because the execution of ssjsSelectFunction's code is too late. It gets executed during the refresh of panel "AcordCadru" caused by parameter refreshID. All fields positioned in front of xc:viewpicklist get refreshed before ssjsSelectFunction's code execution. That's why inputText24 doesn't get the new selected value but inputText25 which comes after xc:viewpicklist does.
If you put inputText24 behind xc:viewpicklist then it will get the new selected value.
But, probably you want to have field inputText24 first and the picklist button xc:viewpicklist after. For this
delete the ssjsSelectFunction code
add a computed field in front of inputText24 with pretty the same code
<xp:text
escape="true"
id="computedField1">
<xp:this.value><![CDATA[#{javascript:
var unid = viewScope.unid;
if (unid && unid !== Contr.sv) {
var doc = database.getDocumentByUNID(unid);
var val1 = doc.getItemValueString("txt_numeAcord_1");
Contr.setValue("acord",val1);
Contr.setValue("sv",unid);
}
return "";
}]]></xp:this.value>
</xp:text>
It will set the new selected values to document and made them visible in inputText24 and inputText25 right away.

Xpage error message - Engine Exception name can't be null IBM WebSphere Application Server

I have created a simple xpage in Domino Designer/Server 9. When opening it, it give following error message:
Engine Exception
name can't be null
IBM WebSphere Application Server
I am not able to locate the source of this error. And strange thing is why IBM Websphere message is coming here!!
<xp:this.beforePageLoad>
<![CDATA[#{javascript:var catDb:NotesDatabase = session.getDatabase("<server name>","catalog.nsf");
requestScope.DocCol = catDb.search("Form='Notefile'"); }]]>
</xp:this.beforePageLoad>
<xp:dataTable id="dataTable1" rows="30" value="#{javascript:return requestScope.DocCol;}" var="repCol" indexVar="repIndex">
<xp:column id="column1">
<xp:text escape="true" id="computedField1" value="#{repCol.Pathname}">
</xp:text>
</xp:column>
</xp:dataTable>
You might want to rework your code a little bit. Along this lines:
<xp:dataTable id="dataTable1" rows="30"
value="#{javascript:return requestTools.getDocumentsByForm('Notefile');}"
var="repCol" indexVar="repIndex">
<xp:column id="column1">
<xp:text escape="true" id="computedField1" value="#{repCol.Pathname}">
</xp:text>
</xp:column>
</xp:dataTable>
Create a script library where you then implement the function. Something like:
var requestTools = {
"isDebug" : function() { return false; },
"debugDocumentsByForm" : function(formName) { return {"PathName" : "DemoPath"},
"getDocumentsByForm" : function(formName) {
if (requestTools.isDebug()) {
return requestTools.debugDocumentsByForm(formName);
} else if (!requestScope.DocCol) {
// optimize this, add only the fields needed to JSON objects, so
// recycling can happen
var catDb:NotesDatabase = session.getDatabase("<server name>","catalog.nsf");
requestScope.DocCol = catDb.search("Form='"+formName+"'");
}
return requestScope.DocCol;
}
}
This will allow you to tune the function without touching all XPages that use it. db.search is the slowest way to perform a search, so you only might use it for testing.
There is no code in the beforePageLoad event. You want to keep the data acquisition confined to your dataTable. Also consider to use a JSON object instead of a document collection and a view or at least an FTSearch. db.Search is way to slow.

Resources