XPages - View doesn't update when a partial refresh occured - xpages

I have a page bound to a doc data source. At the top of the page is a panel where the fields for the doc is set. In the bottom of the page is a view of the docs.
Let's say the fields are [A] and [B], and [B]'s value depends on [A], which partial refreshes [B] on some value change. When I just set [A] that doesn't trigger the partial refresh then press submit/save, the doc is saved and the page updates fully and the doc appears in the view below.
BUT if I set [A] such that [B] refreshes then press submit/save, the doc is saved BUT the doc doesn't appear in the view. I need to reload the page by pressing ENTER in the URL bar to update the view. Tried to do a research on this but to no avail.
What do you think I can do to update the view on the last scenario?
Here is the simplified 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"
style="font-size:11pt;font-weight:bold">
<xp:this.beforePageLoad>
<![CDATA[#{javascript:var currLocation=context.getUrl();
var webDBPath=#LeftBack(currLocation,"/");
sessionScope.jQuery=webDBPath+"/jquery.min.js";
sessionScope.jQueryUI=webDBPath+"/jquery-ui.min.js";
sessionScope.jQueryBlockUI=webDBPath+"/jquery.blockUI.js"}]]>
</xp:this.beforePageLoad>
<xp:this.data>
<xp:dominoDocument var="attachmentDoc" formName="Attachment"></xp:dominoDocument>
</xp:this.data>
<xp:this.resources>
<xp:script src="#{javascript:sessionScope.jQuery}"
clientSide="true">
</xp:script>
<xp:script src="#{javascript:sessionScope.jQueryUI}"
clientSide="true">
</xp:script>
<xp:script src="#{javascript:sessionScope.jQueryBlockUI}"
clientSide="true">
</xp:script>
<xp:script src="/home.js" clientSide="true"></xp:script>
<xp:styleSheet href="/style.css"></xp:styleSheet>
<xp:styleSheet href="/jquery-ui.css"></xp:styleSheet>
<xp:script src="/utils.jss" clientSide="false"></xp:script>
</xp:this.resources>
<xp:span style="font-weight:bold;font-size:11pt"></xp:span>
<xp:span style="font-size:14pt"></xp:span>
<xp:span style="font-weight:bold;font-size:11pt"></xp:span>
<xp:inputText id="reUploadAttachmentID" style="display: none;"
styleClass="reUploadAttachmentID"></xp:inputText>
<xp:br style="font-size:11pt"></xp:br>
<xp:panel style="margin-left:auto;margin-right:auto;width:940.0px"
id="mainPanel">
<xp:span style="font-size:14pt"></xp:span>
<xp:span style="font-size:14pt"></xp:span>
<xp:br style="font-weight:bold"></xp:br>
<xp:br></xp:br>
<xp:inputText id="errorMessage" value="#{requestScope.errorMessage}"
styleClass="errorMessage"></xp:inputText>
<xp:span style="font-weight:bold"></xp:span>
<xp:span style="font-weight:bold">
<xp:span style="font-weight:bold"></xp:span>
</xp:span>
<xp:br></xp:br>
<xp:panel styleClass="upload-details-panel">
<xp:span>Upload:</xp:span>
<xp:fileUpload id="fileUpload1" value="#{attachmentDoc.Attachment}"></xp:fileUpload>
</xp:panel>
<xp:panel styleClass="upload-details-panel">
<span>Type:</span>
<xp:comboBox id="cbUploadType" value="#{attachmentDoc.File_Type}"
styleClass="cbUploadType">
<xp:selectItem itemLabel="Attachment"></xp:selectItem>
<xp:selectItem itemLabel="eCR Master File"></xp:selectItem>
<xp:selectItem itemLabel="Financial Analysis"></xp:selectItem>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="panelUploadDetails">
</xp:eventHandler>
</xp:comboBox>
</xp:panel>
<xp:panel id="panelUploadDetails">
<xp:panel styleClass="upload-details-panel">
<xp:this.rendered><![CDATA[#{javascript:var uploadType = getComponent("cbUploadType").getValue();
if(uploadType == "Attachment" || uploadType == null){
return false;
}
return true;}]]></xp:this.rendered>
<span>Division:</span>
<xp:comboBox id="comboBox1" value="#{attachmentDoc.File_Database}"
styleClass="cbUploadDatabase">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var options = ["---"];
return options.concat(#Unique(#DbColumn("", "eCR Database Settings", 1)));}]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial"
refreshId='#{javascript:var uploadType = getComponent("cbUploadType").getValue();
if(uploadType == "Financial Analysis"){
return "panelFAType";
}
return "panelExtra";
}'>
</xp:eventHandler>
</xp:comboBox>
</xp:panel>
<xp:panel id="panelExtra">
<!--
this is just used to redirect partial refresh of Division
Selection for non-FA
-->
</xp:panel>
<xp:panel styleClass="upload-details-panel" id="panelFAType">
<xp:this.rendered><![CDATA[#{javascript:var uploadType = getComponent("cbUploadType").getValue();
if(uploadType == "Financial Analysis"){
return true;
}
return false;}]]></xp:this.rendered>
<span>Financial Analysis Type:</span>
<xp:comboBox id="comboBoxFAType" value="#{attachmentDoc.FAType}">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var division = getComponent("comboBox1").getValue();
if(division != null){
return getFATypeOptions(getComponent("comboBox1").getValue());
}
return "---";}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</xp:panel>
</xp:panel>
<xp:panel styleClass="upload-details-panel">
<span></span>
<xp:button id="btnUpload" value="Upload" styleClass="btnUpload"
style="height:26.0px">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete" immediate="false" save="true">
<xp:this.action><![CDATA[#{javascript:
var fileData:com.ibm.xsp.http.UploadedFile = facesContext.getExternalContext().getRequest().getParameterMap().get(getClientId('fileUpload1'));
var db:NotesDatabase = session.getCurrentDatabase();
var agent = database.getAgent("Import Data to Document");
//var attDoc:NotesDocument = attachmentDoc.getDocument();
//var doc:NotesDocument = db.createDocument();
var doc:NotesDocument = attachmentDoc.getDocument();
var settingsDoc:NotesDocument = db.getProfileDocument("eCRFilesDBConfiguration", "");
var repositoryPath:String;
if (fileData != null) {
//doc.replaceItemValue('Form', 'Attachment');
doc.computeWithForm(true, false);
var clientFileName:String = fileData.getClientFileName();
var newFile:java.io.File = new java.io.File(fileData.getServerFileName());
var filePath:string = doc.getItemValueString("File_Path");
doc.replaceItemValue('File_Name', clientFileName);
// get file extension
var extension:string = '';
var newFileName:string = '';
var i:int;
i = clientFileName.lastIndexOf('.');
if (i > 0) {
extension = clientFileName.substring(i+1);
}
doc.replaceItemValue('File_Extension', extension);
newFileName = doc.getUniversalID() + '.' + extension;
//var savedFile:java.io.File = new java.io.File('C:\\' + newFileName);
//var savedFile:java.io.File = new java.io.File('C:\\' + clientFileName);
repositoryPath = settingsDoc.getItemValueString("FileRepositoryPath")
var savedFile:java.io.File = new java.io.File(repositoryPath + newFileName);
newFile.renameTo(savedFile);
doc.replaceItemValue("File_Size", savedFile.length())
doc.replaceItemValue("Processed_eCR_Template", "");
// Save the new file
if (savedFile.exists()) {
// this is used to retain the icon/appearance of the attachment
// in the document
//doc.replaceItemValue('Attachment', attDoc.getItemValue('Attachment'));
doc.save();
} else {
//requestScope.errorMessage = 'Server file not found';
print('Server file not found');
}
} else {
requestScope.errorMessage = 'No File found';
print('No File found');
}
// this code prevents resubmit of the uploaded file when the user refreshes
// the page
// var curURL = window.location.href;
// var NSFURL = curURL.toLowerCase().split( '.nsf')[0] + '.nsf';
// window.location.href = NSFURL}]]></xp:this.action>
<xp:this.script><![CDATA[//validate fields before submission
var uploadType = document.getElementById("#{id:cbUploadType}").value;
if(uploadType == "Attachment"){
return true;
}else{
var division = document.getElementById("#{id:comboBox1}").value;
if(division == "---"){
alert("Please specify the division.");
return false;
}
if(uploadType == "eCR Master File"){
return true;
}else if(uploadType == "Financial Analysis"){
var faType = document.getElementById("#{id:comboBoxFAType}").value;
if(faType == "---"){
alert("Please specify the Financial Analysis Type.");
return false;
}else{
return true;
}
}
}
//if upload type not rcognized
alert("Upload Type not recognized. Please contact you administrator.");
return false;
]]></xp:this.script>
</xp:eventHandler>
</xp:button>
</xp:panel>
<xp:panel id="panelUploadedFiles">
<xp:viewPanel rows="30" id="viewPanel1" viewStyle="width:100%">
<xp:this.facets>
<xp:pager partialRefresh="true" layout="Previous Group Next"
xp:key="headerPager" id="pager1">
</xp:pager>
</xp:this.facets>
<xp:this.data>
<xp:dominoView var="view1" viewName="Attachments For Web"
keys="#{javascript:#UserName()}" categoryFilter="File_Owner">
</xp:dominoView>
</xp:this.data>
<xp:viewColumn columnName="File_Name" id="viewColumn2">
<xp:viewColumnHeader value="File Name"
id="viewColumnHeader2">
</xp:viewColumnHeader>
</xp:viewColumn>
<xp:viewColumn columnName="Date_Uploaded" id="viewColumn3">
<xp:viewColumnHeader value="Date Uploaded"
id="viewColumnHeader3">
</xp:viewColumnHeader>
</xp:viewColumn>
<xp:viewColumn columnName="Last_Attached" id="viewColumn4">
<xp:viewColumnHeader value="Last Attached"
id="viewColumnHeader4">
</xp:viewColumnHeader>
</xp:viewColumn>
</xp:viewPanel>
</xp:panel>
</xp:panel>
<xp:br></xp:br>
</xp:view>
The elements that triggers the partial refresh are comboboxes (onchange). The save button is the "Upload" button. The panel panelUploadedFiles contains the view.

You need to post sample code, as there is no way to diagnose your issue from your initial question.
I would recommend to take the "XPages MasterClass" training. It is roughly about four hours. It will show you how to use the XPages Toolbox, which you can use to debug these kinds of issues.

Related

Get selected documents from a view and save as separate document

I am trying to get selected documents from a view and save as separate documents
Here is the design of the xpage
A combo box on the top, a view with check box (this view is used for selection), a button for save the selection values from the view and the combo box. Also there will another view which will display the saved values.
From this post, I can get the unid of selected documents and save to view scope variable. The add button can save the selected value from the combo box and the view and show the result in another view.
However, if I choose more than one value in the view and click save, it saves all values in one document. So I try to use for loop to loop through the selected values in view and save, it still saves one value only in one document.
<xp:table id="table1a">
<xp:tr>
<xp:td id="table1">
<xp:comboBox id="comboBox1"
dojoType="dijit.form.ComboBox" style="width:250.0px"
value="#{document1.Category}">
<xp:selectItems id="selectItems3">
<xp:this.value><![CDATA[#{javascript:var SetFirstValueBlank = #Text("");
return SetFirstValueBlank;
}]]></xp:this.value>
</xp:selectItems>
<xp:selectItems id="selectItems4">
<xp:this.value><![CDATA[#{javascript:#Unique(#DbColumn(#DbName(), "CategoryListView", 1));}]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="table1a">
</xp:eventHandler>
</xp:comboBox>
<xp:text escape="true" id="computedField1">
</xp:text>
</xp:td>
</xp:tr>
<xp:tr>
<xp:td>
<xp:viewPanel rows="10" id="viewPanel1" var="rowData">
<xp:this.data>
<xp:dominoView var="view1"
viewName="hListView">
</xp:dominoView>
</xp:this.data>
<xp:viewColumn columnName="ItemName"
id="viewColumn1" style="background-color:rgb(255,255,255)"
showCheckbox="true">
<xp:viewColumnHeader value="Item Name"
id="viewColumnHeader1" rendered="false">
</xp:viewColumnHeader>
</xp:viewColumn>
<xp:this.facets>
<xp:pager partialRefresh="true"
layout="Previous Group Next" xp:key="footerPager" id="pager2">
</xp:pager>
</xp:this.facets>
</xp:viewPanel>
<xp:br></xp:br>
<xp:button value="Add" id="button1"
style="height:35.0px">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:var Category = getComponent("comboBox1").getValue();
var viewPanel=getComponent("viewPanel1");
var docIDArray=viewPanel.getSelectedIds();
var unidArray = new Array();
for(i=0; i < docIDArray.length; i++) {
var unid=database.getDocumentByID(docIDArray[i]).getUniversalID();
unidArray.push(unid);
}
viewScope.put("unidArray", #Implode(unidArray, ","));
for(var i=0; i< unidArray.length;i++ )
{
document1.replaceItemValue("ItemName", unidArray[i]);
document1.save();
}
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:br></xp:br>
<xp:br></xp:br>
<xp:viewPanel rows="6" id="viewPanel2">
<xp:this.data>
<xp:dominoView var="view2" viewName="CategoryItemView">
<xp:this.categoryFilter><![CDATA[#{javascript:getComponent("comboBox1").getValue();}]]></xp:this.categoryFilter>
</xp:dominoView>
</xp:this.data>
<xp:this.rendered><![CDATA[#{javascript:var value = getComponent("comboBox1").getValue();
if(value =="" || value == null)
{
return false;
}
else
{
return true;
}}]]></xp:this.rendered><xp:viewColumn id="viewColumn4" columnName="Category" rendered="false">
<xp:this.facets>
<xp:viewColumnHeader xp:key="header" id="viewColumnHeader4" value="Category">
</xp:viewColumnHeader>
</xp:this.facets>
</xp:viewColumn>
<xp:viewColumn id="viewColumn3" columnName="$10">
<xp:this.facets>
<xp:viewColumnHeader xp:key="header" id="viewColumnHeader3" value="Category">
</xp:viewColumnHeader>
</xp:this.facets>
</xp:viewColumn>
<xp:viewColumn columnName="ItemName" id="viewColumn2">
<xp:viewColumnHeader value="Item" id="viewColumnHeader2">
</xp:viewColumnHeader>
</xp:viewColumn>
<xp:this.facets>
<xp:pager partialRefresh="true" layout="Previous Group Next" xp:key="footerPager" id="pager3">
</xp:pager>
</xp:this.facets></xp:viewPanel><xp:br></xp:br></xp:td>
</xp:tr>
</xp:table>
Would someone let me know how to save multiple values in separate documents please? Thank you.
(edit: some of previous content are removed)
I think I will focus on how to save multiple value as separate documents first because this part is quite important in the program, once I can save as separate documents, there will another function that needs the result to process.
I review the code, I think I will still use for loop but unfortunately, it still saves one document only.
I'm guessing the document1 object is bound to a on the XPage, which is only created when the XPage is opened. To cause your button to create multiple documents, the for loop needs to modified :
var oneOfMany : NotesXspDocument;
for(var i=0; i< unidArray.length;i++ )
{
oneOfMany = database.createDocument();
oneOfMany.replaceItemValue( "Category", document1.getItemValue("Category" ) );
oneOfMany.replaceItemValue("ItemName", unidArray[i]);
oneOfMany.replaceItemValue("form", "MyFormName" );
oneOfMany.save();
}
Because it no longer uses document1, this loop will need to populate the other items you need such as the form, for example MyFormName as in the example.

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.

Can someone help me learn how to use the javascript connections code?

I am trying to access data from Connections. I need to use some of the javascript api code: https://greenhouse.lotus.com/sbt/SBTPlayground.nsf/JavaScriptSnippets.xsp#snippet=Social_Files_Get_My_Files
But I do not know how to build the app using xPages. I tried a new xPage and pasted the code into a script block but I get compile errors.
Can someone show me how to use the Javascript samples from the playground?
Paul's suggestion to use the openntf ticket tracking was brilliant! Here is the code that ultimately worked. Thank you again Paul!
<?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:dataView id="myFilesDataView" var="file" rows="110"
columnTitles="true" styleClass="filesDataView">
<xe:this.extraColumns>
<xe:viewExtraColumn columnTitle="Filetype">
</xe:viewExtraColumn>
<xe:viewExtraColumn columnTitle="Size">
</xe:viewExtraColumn>
</xe:this.extraColumns>
<xe:this.summaryColumn>
<xe:viewSummaryColumn columnTitle="Filename">
</xe:viewSummaryColumn>
</xe:this.summaryColumn>
<xp:this.value>
<![CDATA[#{javascript:
try{
var filesService = new com.ibm.sbt.services.client.connections.files.FileService( "connectionsSSO" );
// ps:100 is page size of 100 files
var myFiles = filesService.getMyFiles({ps:100});
viewScope.myFilesAvailable = true;
return myFiles;
}catch(exception){
println("getFiles value error: " + exception);
viewScope.myFilesAvailable = false;
return null;
}}]]>
</xp:this.value>
<xp:this.facets>
<xp:panel xp:key="noRows" id="emptyMyFilesPanel">
<xp:div styleClass="lotusWidgetBody">
<xp:text>
<xp:this.value>
<![CDATA[#{javascript:
return (viewScope.myFilesAvailable ? "No files found." : "Files unavailable.");
}]]>
</xp:this.value>
</xp:text>
</xp:div>
</xp:panel>
<xp:panel id="summaryPanel" xp:key="summary" style="white-space:nowrap;">
<xp:link escape="true" id="link7" target="_blank"
text="#{javascript:return file.getTitle();}" styleClass="dataViewLink">
<xp:this.value><![CDATA[#{javascript:return file.getContentUrl();}]]>
</xp:this.value>
</xp:link>
</xp:panel>
<xp:panel id="typePanel" xp:key="extra0"
style="width: 20%;white-space:nowrap;">
<xp:text>
<xp:this.value><![CDATA[#{javascript:return file.getType();}]]></xp:this.value>
</xp:text>
</xp:panel>
<xp:panel id="sizePanel" xp:key="extra1"
style="width: 15%;white-space:nowrap;">
<xp:text>
<xp:this.value><![CDATA[#{javascript:
var size = file.getSize();
var kilobyte = 1024;
var megabyte = kilobyte *1024;
if(size < kilobyte) {
return (size + " B");
}else if(size < megabyte) {
return (Math.round(size/kilobyte) + " KB");
}else {
return (Math.round(size/megabyte) + " MB");
}}]]>
</xp:this.value>
</xp:text>
</xp:panel>
</xp:this.facets>
</xe:dataView>
</xp:view>

Get handle to the documents inside a panel which is within a repeat control from outside the repeat control

I am working on this functionality where-in I need to provide the user with a list of documents and provide an option for the user to change/add values to a field(s) inside these documents. I was going through this example Xpages - Display filtered Document Collection in a repeat control and did a similar implementation and got it to work. So what I have now is a panel inside a repeat which has its data source set with the form and document id set to return the value in the repeat control variable (which is the document UNID from the document collection), thus I am able to bind fields directly to these documents using the data source defined in the panel. The challenge is that I want to get the handle to these documents to set a particular value in them and also save the values in the fields that I bind to the back-end document. Is there any way I can access the documents from outside the repeat control (let say on the click of a button)? Following is my code for the repeat:
<xp:repeat id="rptApprDocuments" rows="30" var="apprDoc"
indexVar="docIndex" first="0">
<xp:this.value><![CDATA[#{javascript:// Look up the employee details view to get the employee appraisal details from the current database
var curDB:NotesDatabase = session.getCurrentDatabase();
var vwlkApprView:NotesView = curDB.getView("vwlkApprAllFGCompAppr");
var collDocAppr:NotesDocumentCollection = vwlkApprView.getAllDocumentsByKey(sessionScope.key);
var apprDocCount = collDocAppr.getCount();
if(apprDocCount != 0){
var docAppr:NotesDocument;
var docUNIDArray = new Array();
for(i=0;i<apprDocCount;i++){
docAppr = collDocAppr.getNthDocument(i+1);
//print(docAppr.getUniversalID());
docUNIDArray.push(docAppr.getUniversalID());
}
viewScope.put("docUNIDArray",docUNIDArray);
return docUNIDArray;
/*return collDocAppr;
/return sortColByItemName(collDocAppr, "AppraiseeCWLCluster");*/
}
return null;
]]></xp:this.value>
<xp:panel id="pnlRR">
<xp:this.data>
<xp:dominoDocument formName="frmAppraisal" var="appraisalDoc"
action="editDocument" ignoreRequestParams="true">
<xp:this.postSaveDocument><![CDATA[#{javascript:if(requestScope.SubmitRR == true){
appraisalDoc.setValue("ApperRRStatus","1");
appraisalDoc.save();
}}]]></xp:this.postSaveDocument>
<xp:this.documentId><![CDATA[#{javascript://apprDoc.getUniversalID();
return apprDoc;}]]></xp:this.documentId>
</xp:dominoDocument>
</xp:this.data>
<xp:tr>
<xp:td styleClass="tdCls" style="width:2%">
<xp:label id="SrNo">
<xp:this.value><![CDATA[#{javascript:var index = parseInt(docIndex)
index = index + 1;
index.toString();}]]></xp:this.value>
</xp:label>
</xp:td>
<xp:td styleClass="tdCls" style="width:20.0%">
<xp:label id="ApeName">
<xp:this.value><![CDATA[#{javascript://return apprDoc.getItemValueString("AppraiseeName");
return appraisalDoc.getItemValueString("AppraiseeName");}]]></xp:this.value>
</xp:label>
</xp:td>
<xp:td styleClass="tdCls" style="width:8.0%">
<xp:label id="ApeGrade">
<xp:this.value><![CDATA[#{javascript://return apprDoc.getItemValueString("Appraisee_Grade");
return appraisalDoc.getItemValueString("Appraisee_Grade");}]]></xp:this.value>
</xp:label>
</xp:td>
<xp:td styleClass="tdCls" style="width:15.0%">
<xp:div style="text-align:center">
<xp:label id="appeTotImpRate"
style="font-size:10pt;color:rgb(255,0,0);font-weight:bold">
<xp:this.value><![CDATA[#{javascript://return apprDoc.getItemValueDouble("AppeTotImpRate").toFixed(2);
return appraisalDoc.getItemValueDouble("AppeTotImpRate").toFixed(2);}]]></xp:this.value>
</xp:label>
</xp:div>
</xp:td>
<xp:td styleClass="tdCls" style="width:15.0%">
<xp:div style="text-align:center">
<xp:label id="apprTotImpRate"
style="color:rgb(255,0,0);font-size:10pt;font-weight:bold">
<xp:this.value><![CDATA[#{javascript://return apprDoc.getItemValueDouble("ApprTotImpRate").toFixed(2);
return appraisalDoc.getItemValueDouble("ApprTotImpRate").toFixed(2);}]]></xp:this.value>
</xp:label>
</xp:div>
</xp:td>
<xp:td styleClass="tdCls" style="width:15.0%">
<xp:div style="text-align:center">
<xp:label id="revTotImpRate"
style="font-size:10pt;color:rgb(255,0,0);font-weight:bold">
<xp:this.value><![CDATA[#{javascript://return apprDoc.getItemValueDouble("RevTotImpRate").toFixed(2);
return appraisalDoc.getItemValueDouble("RevTotImpRate").toFixed(2);}]]></xp:this.value>
</xp:label>
</xp:div>
</xp:td>
<xp:td styleClass="tdCls" style="width:12.0%">
<xp:div
style="font-size:10pt;color:rgb(255,0,0);font-weight:bold;text-align:center">
<xp:comboBox id="apprGrades" style="width:50.0px"
disableClientSideValidation="true" value="#{appraisalDoc.ApperFinalGrade}"
readonly="true">
<xp:selectItem itemLabel="-" itemValue=""
id="selectItem1">
</xp:selectItem>
<xp:selectItem itemLabel="1" itemValue="1"
id="selectItem2">
</xp:selectItem>
<xp:selectItem itemLabel="2" itemValue="2"
id="selectItem3">
</xp:selectItem>
<xp:selectItem itemLabel="3" itemValue="3"
id="selectItem4">
</xp:selectItem>
<xp:selectItem itemLabel="4" itemValue="4"
id="selectItem5">
</xp:selectItem>
<xp:selectItem itemLabel="5" itemValue="5"
id="selectItem6">
</xp:selectItem>
</xp:comboBox>
</xp:div>
</xp:td>
<xp:td styleClass="tdCls" style="width:12.0%">
<xp:div
style="font-size:10pt;color:rgb(255,0,0);font-weight:bold;text-align:center">
<xp:comboBox id="ApperRelativeRank" style="width:50.0px"
disableClientSideValidation="true" value="#{appraisalDoc.ApperRelativeRank}">
<xp:this.readonly><![CDATA[#{javascript:/*if(compositeData.UserRole == "Appraiser"){
return true;
}
if(parseInt(appraisalDoc.getValue("CurrFGRRStatus")) >= parseInt(compositeData.compStatus)){
return true;
}*/
return false;}]]></xp:this.readonly>
<xp:this.rendered><![CDATA[#{javascript:/*if(compositeData.UserRole == "Appraiser"){
return false;
}*/
return true;}]]></xp:this.rendered>
<xp:selectItem itemLabel="-" itemValue=""
id="selectItem13">
</xp:selectItem>
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:// Look up the employee details view to get the employee appraisal details from the current database
var curDB:NotesDatabase = session.getCurrentDatabase();
var vwlkApprView:NotesView = curDB.getView("vwlkCWLApprAllFGCompAppr");
var cwlCluster = appraisalDoc.getItemValueString("AppraiseeCWLCluster");
var collEntAppr:NotesViewEntryCollection = vwlkApprView.getAllEntriesByKey(sessionScope.key + cwlCluster);
var entCount = collEntAppr.getCount()
if(entCount != 0){
var ranks = new Array();
var rankValue, rankLabel;
for(i=0;i<entCount;i++){
rankValue = i + 1;
rankLabel = rankValue + "/" + entCount;
ranks.push(rankLabel + "|" + rankValue);
}
return ranks;
}
return null;}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</xp:div>
</xp:td>
</xp:tr>
</xp:panel>
</xp:repeat>
You can access the data sources of a panel, see http://xpageswiki.com/web/youatnotes/wiki-xpages.nsf/dx/Work_with_datasources#Reset+%2F+clear+a+datasource for example code.
But that solves only half of the problem, you need a handle to each panel inside the repeater.
You can find an XPages API browser on openNTF (I don't know the exact name at the moment). Taking this, you can examine the repeat's control at runtime and check for methods and properties. I bet there is something to get components that are inside the repeater.

How can I set focus to Edit Box inside repeat control?

I would like to set focus + place cursor to an Edit Box (the last one) within a repreat control. The repeat is inside a panel (panelRep). I then have a button outside the panel.
This is the client side code for the button which almost works.. Focus is set (blue border around field), but cursor is not placed in field.
User must still click the field to be able to write input.
Example without focus:
Example with focus:
Client side code for button which sets focus to last Edit Box in which id contains the string inputKode:
try {
var el = dojo.query('div[id*="inputKode"]');
var node = el[el.length-1];
setTimeout(function() { node.focus(); }, 500);
//node.focus();
} catch (e) { }
Code for panelRep:
<xp:panel id="panelRep">
<xp:repeat id="repeat1" rows="12" var="row" indexVar="idx"
value="#{view1}" repeatControls="false">
<xp:panel id="panelLinje">
<xp:this.data>
<xp:dominoDocument formName="frmPBudKodeVerdi"
var="dsdoc" action="editDocument" computeWithForm="both"
documentId="#{javascript:row.getUniversalID();}">
</xp:dominoDocument>
</xp:this.data>
<xp:table style="width:800.0px">
<xp:tr>
<xp:td style="width:100px">
<xp:inputText id="inputKode"
value="#{dsdoc.KodeNr}" style="width:62px">
<xp:this.attrs>
<xp:attr name="tabindex"
value="#{javascript:return idx + '1';}">
</xp:attr>
</xp:this.attrs>
<xp:typeAhead mode="partial"
minChars="1" var="lukey" valueMarkup="true" id="typeAhead1">
<xp:this.valueList><![CDATA[#{javascript://var type = compositeData.type;
return TypeAheadKode2(sessionScope.type,lukey);
}]]></xp:this.valueList>
</xp:typeAhead>
<xp:eventHandler event="onchange"
submit="true" refreshMode="partial" refreshId="panelLinje">
<xp:this.action><![CDATA[#{javascript:onChangeKode();}]]></xp:this.action>
</xp:eventHandler>
</xp:inputText>
</xp:td>
<xp:td style="width:450px">
<xp:inputText id="inputNavn"
value="#{dsdoc.KodeNavn}" style="width:440px"
readonly="true">
</xp:inputText>
</xp:td>
<xp:td style="width:60px">
<xp:inputText id="inputNorm"
style="width:45px" value="#{dsdoc.NormPrProd}"
rendered="#{javascript:viewScope.visNorm}" readonly="true">
<xp:this.attrs>
<xp:attr name="tabindex"
value="#{javascript:return idx + '2';}">
</xp:attr>
</xp:this.attrs>
<xp:this.converter>
<xp:convertNumber
type="number">
</xp:convertNumber>
</xp:this.converter>
</xp:inputText>
</xp:td>
<xp:td style="width:50px">
<xp:inputText id="inputAntall"
style="width:45px" value="#{dsdoc.NormAntall}"
rendered="#{javascript:viewScope.visNorm}">
<xp:this.converter>
<xp:convertNumber
type="number">
</xp:convertNumber>
</xp:this.converter>
<xp:eventHandler
event="onchange"
submit="true"
refreshMode="partial"
refreshId="inputTimer">
<xp:this.action><![CDATA[#{javascript:onChangeAntall()}]]></xp:this.action>
</xp:eventHandler>
<xp:this.attrs>
<xp:attr name="tabindex"
value="#{javascript:return idx + '3';}">
</xp:attr>
</xp:this.attrs>
</xp:inputText>
</xp:td>
<xp:td
style="width:50px;text-align:right">
<xp:inputText id="inputTimer"
value="#{dsdoc.Timer}" style="width:45px;text-align:right">
<xp:this.converter>
<xp:convertNumber
type="number">
</xp:convertNumber>
</xp:this.converter>
<xp:this.attrs>
<xp:attr name="tabindex"
value="#{javascript:return idx + '4';}">
</xp:attr>
</xp:this.attrs>
</xp:inputText>
</xp:td>
<xp:td>
</xp:td>
</xp:tr>
</xp:table>
<xp:eventHandler event="onClientLoad" submit="true"
refreshMode="norefresh">
</xp:eventHandler>
</xp:panel>
</xp:repeat>
</xp:panel>
Update 22.09.2012:
#MarkyRoden - Thanks for pointing me in the right direction.
After refining the dojo.query selector, I ended up with 1 line of code.
var el = dojo.query('div[id*="inputKode"] .dijitInputField > input').at(-1)[0].focus();
Original post:
I found out that the element being set focus on was not an INPUT element.
Element id started with widget_
E.g widget_view:_id1:_id2:_id3:repeat1:8:inputKode if there are 8 rows in the repeat
I then discovered that the nodeType of the element was DIV
By viewing the element.innerHTML, I discovered that it had multiple children.
I tried to use element.querySelector or element.querySelectorAll, but I couldn't get them to work for the element, so I ended up looping through element.childNodes.
Not very pretty, but it does the work for now..
I'm sure it can be done much nicer by adding elements to the dojo.query selector, or by using jquery. Have to look into that later..
Well, here's the code I put in the onClientLoad event for my CC:
var el = dojo.query('div[id*="inputKode"]');
var node = el[el.length-1];
node.focus();
var activeElementId = document.activeElement.id;
var activeElement = dojo.byId( activeElementId );
var kids = activeElement.childNodes;
for(var i=0; i < kids.length; i++)
{
if(kids[i].className == 'dijitReset dijitInputField dijitInputContainer')
{
var elementDiv = kids[i];
var elementDivKids = elementDiv.childNodes;
for(var j=0; j < elementDivKids.length; j++)
{
var elementInput = elementDivKids[j];
elementInput.focus();
}
}
}
regards,
Petter

Resources