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
Related
I have the following XPage which has one table and only two tr's.
The first one is a button itself which puts into viewScope['showPasswordTr'] boolean true value when clicked first time, when puts false when clicked again.
The second tr has an input which is rendered if viewScope['showPasswordTr']is true.
The problem I've encountered is that I can only click the button only once and it's 100% because of input field present. If I remove it, it works as expected
The second time and so on, the button just freezes and doesn't execute the action specified onclick event. Why is so? And how can I make it work as expected?
Thanks in advance.
EDIT
Well, It's obviously all because of required property set to true... So, should I check the element for emptiness only in the disered control then? Is it a good practice?
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:table id="buttonTable">
<xp:tr id="buttonTr">
<xp:td id="buttonTd">
<xp:button id="authAsPersonButton"
value="This button can be clicked only once" />
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" execId="buttonTable"
refreshId="buttonTable">
<xp:this.action>
<![CDATA[#{javascript:
print("clicked");
if(viewScope['showPasswordTr'])
{
viewScope['showPasswordTr'] = false;
}
else
{
viewScope['showPasswordTr'] = true;
}
}]]>
</xp:this.action>
</xp:eventHandler>
</xp:td>
</xp:tr>
<xp:tr id="passwordLabelTr" rendered="#{javascript:
return viewScope['showPasswordTr'] == true;
}">
<xp:td id="passwordLabelTd">
<xp:text id="passwordText" style="font-size: 14px;">
<xp:this.value>
<![CDATA[#{javascript:
return 'password:';
}]]>
</xp:this.value>
</xp:text>
</xp:td>
<xp:td id="passwordInputTd" align="right">
<xp:inputText id="passwordInput" password="true"
required="true">
</xp:inputText>
</xp:td>
</xp:tr>
</xp:table>
</xp:view>
Add execId="buttonTd" or disableValidators="true" to your eventHandler properties. Then your example works as expected.
I optimized the code a bit (event handling within the button + shorter code for handling viewScope.showPasswordTr):
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:table id="buttonTable">
<xp:tr id="buttonTr">
<xp:td id="buttonTd">
<xp:button id="authAsPersonButton" value="Toggle password field">
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="buttonTable" execMode="partial"
disableValidators="true">
<xp:this.action>
<![CDATA[#{javascript:
viewScope.showPasswordTr = !viewScope.showPasswordTr}]]>
</xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:td>
</xp:tr>
<xp:tr id="passwordLabelTr" rendered="#{!!viewScope.showPasswordTr}">
<xp:td id="passwordLabelTd">
<xp:text id="passwordText" style="font-size: 14px;" value="password:" />
</xp:td>
<xp:td id="passwordInputTd" align="right">
<xp:inputText id="passwordInput" password="true"
required="true">
</xp:inputText>
</xp:td>
</xp:tr>
</xp:table>
</xp:view>
I have following custom control:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.beforePageLoad><![CDATA[#{javascript:compositeData.id = this.getId();
if (!compositeData.body_class) {compositeData.body_class='panel-body'};
if (!compositeData.panel_id) {compositeData.panel_id='section'+compositeData.id};}]]></xp:this.beforePageLoad>
<xp:panel>
<xp:this.styleClass><![CDATA[#{javascript:"ccSectionPanel panel " + compositeData.panel_class + ""}]]></xp:this.styleClass>
<xp:this.attrs>
<xp:attr name="id">
<xp:this.value><![CDATA[#{javascript:compositeData.panel_id}]]></xp:this.value>
</xp:attr>
</xp:this.attrs>
<xp:panel styleClass="panel-heading" style="cursor:pointer;">
<xp:this.attrs>
<xp:attr name="id">
<xp:this.value><![CDATA[#{javascript:compositeData.panel_id + "_heading"}]]></xp:this.value>
</xp:attr>
<xp:attr name="href">
<xp:this.value><![CDATA[#{javascript:"#" + compositeData.panel_id + "_section"}]]></xp:this.value>
</xp:attr>
<xp:attr name="data-toggle" value="collapse"></xp:attr>
</xp:this.attrs>
<xp:link escape="true" styleClass="panel-title"
text="#{javascript:compositeData.titleBarText}">
<xp:this.attrs>
<xp:attr name="id">
<xp:this.value><![CDATA[#{javascript:compositeData.panel_id + "_title"}]]></xp:this.value>
</xp:attr>
</xp:this.attrs>
<xp:this.id><![CDATA[${javascript:compositeData.panel_id + "_title"}]]></xp:this.id>
</xp:link>
</xp:panel>
<xp:panel>
<xp:this.styleClass><![CDATA[#{javascript:"panel-collapse collapse" + (compositeData.initClosed ? "" : " in")}]]></xp:this.styleClass>
<xp:this.attrs>
<xp:attr name="id">
<xp:this.value><![CDATA[#{javascript:compositeData.panel_id + "_section"}]]></xp:this.value>
</xp:attr>
</xp:this.attrs>
<xp:panel
styleClass="#{javascript:compositeData.body_class}">
<xp:callback facetName="panelBody" id="panelBody"></xp:callback>
</xp:panel>
<xp:panel rendered="#{javascript:compositeData.footer}"
styleClass="panel-footer">
<xp:callback facetName="panelFooter" id="panelFooter"></xp:callback>
</xp:panel>
</xp:panel>
</xp:panel>
</xp:view>
I use it in a repeat control:
<xp:repeat id="repeat1" rows="30" value="#{view1}"
var="repEntry" indexVar="index" repeatControls="false">
<xp:panel>
<xp:this.data>
<xp:dominoDocument var="doc"
action="openDocument"
documentId="#{javascript:repEntry.getNoteID()}"
ignoreRequestParams="true">
</xp:dominoDocument>
</xp:this.data>
<xc:ccSectionPanel initClosed="false"
panel_class="#{javascript:repEntry.getColumnValue('class')}"
footer="#{javascript:sessionScope.isAdmin}"
rendered="#{javascript:repEntry.getColumnValue('Status') == '1' || sessionScope.isAdmin}">
<xc:this.titleBarText><![CDATA[#{javascript:repEntry.getColumnValue('Title') + (repEntry.getColumnValue('Status') != '1' ? ' (скрыто)' : '')
}]]></xc:this.titleBarText>
<xp:this.facets>
<xp:panel xp:key="panelFooter">
<xp:button value="Редактировать"
id="button2" styleClass="btn btn-xs">
<i
class="glyphicon glyphicon-pencil">
</i>
<xp:eventHandler event="onclick"
submit="true" refreshMode="complete">
<xp:this.action>
<xp:openPage
name="/index.xsp" target="editDocument"
documentId="#{javascript:repEntry.getNoteID()}">
</xp:openPage>
</xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button
value="#{javascript:repEntry.getColumnValue('Status') != '1' ? 'Показать' : 'Скрыть'}"
id="button3" styleClass="#{javascript:'btn btn-xs'}">
<i
class="#{javascript:repEntry.getColumnValue('Status') != '1' ? 'glyphicon glyphicon-eye-open' : 'glyphicon glyphicon-eye-close'}">
</i>
<xp:eventHandler event="onclick"
submit="true" refreshMode="partial" disableValidators="true"
refreshId="content">
<xp:this.action><![CDATA[#{javascript:if (repEntry.getColumnValue('Status') == '1') {
doc.replaceItemValue('Status','0');
doc.replaceItemValue('Author',sessionScope.User.UserName);
doc.save();
} else {
doc.replaceItemValue('Status','1');
doc.replaceItemValue('Author',sessionScope.User.UserName);
doc.save();
}}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:text escape="false"
id="computedField2" styleClass="btn btn-xs">
<xp:this.value><![CDATA[#{javascript:'<i class="glyphicon glyphicon-user"></i>' + repEntry.getColumnValue('Author') + ' <i class="glyphicon glyphicon-time"></i>' + repEntry.getColumnValue('$1')
}]]></xp:this.value>
</xp:text>
</xp:panel>
<xp:panel xp:key="panelBody">
<!-- <xp:this.data>
<xp:dominoDocument var="doc" action="openDocument"
documentId="#{javascript:repEntry.getNoteID()}"
ignoreRequestParams="true">
</xp:dominoDocument>
</xp:this.data> -->
<xp:inputRichText
id="inputRichText2" value="#{doc.Body}" readonly="true"
rendered="false">
</xp:inputRichText>
<xp:text escape="false"
id="computedField1">
<xp:this.value><![CDATA[#{javascript:doc.getDocument().getFirstItem("Body").getMIMEEntity().getContentAsText(); }]]></xp:this.value>
</xp:text>
</xp:panel>
</xp:this.facets>
</xc:ccSectionPanel>
</xp:panel>
</xp:repeat>
When i set cumputed properties,
It works, but when i set panel_id to something relative to repEntry or doc, it throws error (repEntry is undefined). I can set "Create controls at page creation", but then I lose advantages of partial refresh.
The main question, why one costom property can work with repEntry, but other can't?
The answer comes down to when the property gets calculated. Compute it and add a print statement in the SSJS code and you'll see. IDs need to be calculated when the components get loaded, so at the earliest part of the processing. And most importantly this is when it's generating a single abstract set of components, not associated to a particular row entry, because it's not yet built the collection. Think of it like creating an abstract class before creating objects from it.
I am opening a dialog box in an Xpage. In the dialog box I am displaying some fields from 3 other documents, and allowing the user to save some notes. All of this works, except I want to display attachments if there are any. I entered a file download control and for the data source pointed to the target document and did a
tmpDoc.getAttachment("attachments")
to get the attachments. But nothing shows up.
Here is the code from the one row in the table in the dialog box.
The other fields work fine, and I know I am getting the tmpDoc, but how do I display the attachment so the user can view it?
<xp:td>
<xp:fileDownload
rows="30"
id="fileDownload1"
displayLastModified="false">
<xp:this.value><![CDATA[#{javascript:
var prtUNID:String = document.getItemValueString("PCTaskParentID");
var tmpView:NotesView = database.getView("(dbAllPCTasksByTaskID)");
var tmpDoc:NotesDocument = tmpView.getDocumentByKey(prtUNID);
tmpDoc.getAttachment("attachments")
}]]></xp:this.value>
</xp:fileDownload>
</xp:td>
I am having more issues with this. Now it does not really work at all.
Here is what I am trying to accomplish.
I have a form PC Build. It is all the tasks that must be done to build a PC in my company. There is a list of Master Tasks called PC Tasks. When a new PC Build is saved, the PC Tasks get copied to rspPCTask forms attached to the PC Build.
As a user works om building a computer they can open up the PC Build and see the individual tasks. I want them to be able to click on a task and pull up the notes and attachments from the master task, while entering notes for the individual task.
Below is a screen shot. In the second field I am grabbing something with javascript. In the first field I am binding the field to the data source, but it is always blank. I cannot figure out why.
I have put in all my code below. Any assistance would be greatly appreciated!!!
<?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"
dojoForm="true"
dojoParseOnLoad="true"
dojoTheme="true">
<xp:this.data>
<xp:dominoDocument
var="document1"
action="openDocument"
computeWithForm="onsave"
formName="PCBuild">
<xp:this.postNewDocument>
<xp:actionGroup>
<xp:setValue
binding="#{document1.ID}"
value="#{javascript:session.evaluate('#Unique')}" />
<xp:setValue
binding="#{document1.crtDte}"
value="#{javascript:session.evaluate('#Today')}" />
<xp:setValue
binding="#{document1.crtUsr}"
value="#{javascript:session.getCommonUserName()}" />
</xp:actionGroup>
</xp:this.postNewDocument>
</xp:dominoDocument>
</xp:this.data>
<xp:this.resources>
<xp:styleSheet
href="/custom.css" />
<xp:script
src="/xpValidationPCBuild.jss"
clientSide="false" />
<xp:script
src="/xpUtilities.jss"
clientSide="false"></xp:script>
<xp:styleSheet
href="/.ibmxspres/dojoroot/dojox/grid/resources/tundraGrid.css">
</xp:styleSheet>
<xp:styleSheet
href="/.ibmxspres/dojoroot/dojox/grid/resources/tundraEnhancedGrid.css">
</xp:styleSheet>
<xp:dojoModule
name="dojox.grid.EnhancedGrid"></xp:dojoModule>
</xp:this.resources>
<xp:this.beforePageLoad><![CDATA[#{javascript:viewScope.ID = document1.getItemValueString("ID")}]]></xp:this.beforePageLoad>
<xp:this.afterPageLoad><![CDATA[#{javascript:viewScope.put("rows","25")}]]></xp:this.afterPageLoad>
<xp:panel
style="width:900.00px">
<xp:panel>
<xp:text
escape="true"
id="dspDocUNID"
style="display:none">
<xp:this.value><![CDATA[#{javascript:if (#IsNewDoc())
{
return "0"
}
else
{
var doc:NotesDocument = document1.getDocument();
var sUNID = doc.getUniversalID();
return sUNID
}}]]></xp:this.value>
</xp:text>
<xp:scriptBlock
id="scriptBlock1">
<xp:this.value><![CDATA[// Conditionally return an image tag to display an icon in a cell
function displayIcon (value) {
var image = '';
switch (value.toLowerCase()) {
case "open":
image = '<img alt="" src="blueUncheckedCheckBox15.png" />';
break;
case "closed":
image = '<img alt="" src="blueCheckedCheckBox15.png" />';
break;
default:
image = '<img alt="" src="greenChk50.png" />';
break;
}
return image;
}]]></xp:this.value>
</xp:scriptBlock>
</xp:panel>
<xe:widgetContainer
id="widgetContainerHeader">
<xp:panel
style="padding-top:8.0px;padding-bottom:8.0px">
<xp:button
id="button1"
value="Edit"
style="font-weight:bold;font-size:10pt"
rendered="#{javascript:!(document1.isEditable())}">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="complete">
<xp:this.action>
<xp:changeDocumentMode
mode="edit" />
</xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button
value="Save"
id="button3"
style="font-weight:bold;font-size:10pt"
rendered="#{javascript:(document1.isEditable())}">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="partial"
refreshId="plContainer">
<xp:this.action>
<xp:actionGroup
condition="#{javascript:validateForm()}">
<xp:saveDocument
var="document1"></xp:saveDocument>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript://Get handle on current doc and see if it is a new doc
var thisDoc:NotesDocument = document1.getDocument();
var tg = thisDoc.getItemValueString("tasksGenerated");
if (tg != "Y") {
//Set flag to Y and save document
thisDoc.replaceItemValue("tasksGenerated","Y")
thisDoc.save(true)
var rspDoc:NotesDocument;
//Loop through all PC Task Docs
var pcTasksView:NotesView = database.getView("(dbAllPCTasks)");
var pcTaskDoc:NotesDocument = pcTasksView.getFirstDocument();
var tmpDoc:NotesDocument;
while (pcTaskDoc != null)
{
//Make new doc and add as response to this doc
rspDoc = database.createDocument();
rspDoc.replaceItemValue("Form","rspPCTask");
rspDoc.replaceItemValue("category",pcTaskDoc.getItemValueString("category"));
rspDoc.replaceItemValue("title",pcTaskDoc.getItemValueString("title"));
rspDoc.replaceItemValue("status","Open");
rspDoc.replaceItemValue("PCBuildParentID",thisDoc.getItemValueString("ID"));
rspDoc.replaceItemValue("PCTaskParentID",pcTaskDoc.getItemValueString("ID"));
rspDoc.replaceItemValue("PCTaskParentUNID",pcTaskDoc.getUniversalID());
rspDoc.replaceItemValue("order",pcTaskDoc.getItemValueInteger("order"));
rspDoc.save();
tmpDoc = pcTasksView.getNextDocument(pcTaskDoc);
pcTaskDoc.recycle();
pcTaskDoc = tmpDoc;
}
}}]]></xp:this.script>
</xp:executeScript>
<xp:openPage
name="$$PreviousPage"></xp:openPage>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button
id="button2"
style="font-weight:bold;font-size:10pt"
value="Close">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="norefresh">
<xp:this.action>
<xp:openPage
name="$$PreviousPage"
target="openDocument" />
</xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:text
escape="true"
id="computedField3"
style="font-size:14pt;color:rgb(79,79,79);padding-left:px;padding-bottom:px;margin-bottom:px;padding-right:25.0px">
<xp:this.value><![CDATA[#{javascript:document1.getItemValueString("crtDte")}]]></xp:this.value>
</xp:text>
</xp:panel>
</xe:widgetContainer>
<xp:panel
id="plContainer">
<xp:panel>
<xe:widgetContainer
id="widgetContainerData">
<xe:formTable
id="frLocationMaster"
disableErrorSummary="true"
disableRowError="true">
<xp:this.facets>
</xp:this.facets>
<xe:formRow
id="formRow5"
labelPosition="none"
style="padding-bottom:10.0px">
<xp:table
style="width:99%"
border="0"
cellpadding="0"
role="presentation"
cellspacing="0"
id="table4">
<xp:tr>
<xp:td
style="width:80.0px;min-width:120px">
<xp:text
id="cfTitle"
xp:key="header"
style="font-size:14pt;color:rgb(79,79,79);padding-left:px;padding-bottom:px;margin-bottom:px">
<xp:this.value><![CDATA[#{javascript:"PC Build"}]]></xp:this.value>
</xp:text>
</xp:td>
<xp:td
style="width:250.0px">
</xp:td>
<xp:td
style="text-align:right">
<xp:text
escape="true"
id="computedField1"
style="font-size:14pt;color:rgb(79,79,79);padding-left:25.0px;padding-bottom:px;margin-bottom:px">
<xp:this.value><![CDATA[#{javascript:document1.getItemValueString("crtUsr") + " on "}]]></xp:this.value>
<xp:this.rendered><![CDATA[#{javascript:if (#IsNewDoc() == 1) {
return false
} else {
return true;
}}]]></xp:this.rendered>
</xp:text>
<xp:text
escape="true"
id="computedField2"
style="font-size:14pt;color:rgb(79,79,79);padding-left:px;padding-bottom:px;margin-bottom:px;padding-right:px"
value="#{document1.CrtDte}">
<xp:this.converter>
<xp:convertDateTime
type="both"
timeStyle="short" />
</xp:this.converter>
<xp:this.rendered><![CDATA[#{javascript:if (#IsNewDoc() == 1) {
return false
} else {
return true;
}}]]></xp:this.rendered>
</xp:text>
</xp:td>
</xp:tr>
</xp:table>
</xe:formRow>
<xe:formRow
id="formRow1"
labelPosition="none">
<xp:table
style="width:99%"
border="0"
cellpadding="0"
role="presentation"
cellspacing="0"
id="table3">
<xp:tr>
<xp:td
style="width:10%;min-width:120px;">
<xp:label
id="label4"
for="formRow1"
value="Employee Name" />
</xp:td>
<xp:td
style="width:100px">
<xp:inputText
value="#{document1.employeeName}"
id="employeeName1">
<xp:typeAhead
mode="full"
minChars="1"
valueListSeparator=","
ignoreCase="true"
id="typeAhead1">
<xp:this.valueList><![CDATA[#{javascript:var dbname = new Array(#Subset(#DbName(), 1),"names.nsf");
return #DbColumn(dbname,"($PeopleByName)",1);}]]></xp:this.valueList>
</xp:typeAhead>
</xp:inputText>
</xp:td>
<xp:td
style="width:20px">
<xe:valuePicker
id="valuePicker1"
for="employeeName1"
pickerIcon="/picker.png"
dialogTitle="Choose Employee">
<xe:this.dataProvider>
<xe:simpleValuePicker>
<xe:this.valueList><![CDATA[#{javascript:var db:NotesDatabase = session.getDatabase(database.getServer(),"names.nsf");
var viewHandle:NotesView = db.getView("($PeopleByName)");
return viewHandle.getColumnValues(0)
}]]></xe:this.valueList>
</xe:simpleValuePicker>
</xe:this.dataProvider>
</xe:valuePicker>
</xp:td>
<xp:td>
<xp:message
id="message1"
for="employeeName1" />
</xp:td>
</xp:tr>
</xp:table>
</xe:formRow>
<xe:formRow
id="formRow2"
labelPosition="none">
<xp:table
style="width:99%"
border="0"
cellpadding="0"
role="presentation"
cellspacing="0"
id="table1">
<xp:tr>
<xp:td
style="width:10%;min-width:120px;">
<xp:label
id="label1"
for="formRow1"
value="Computer Name" />
</xp:td>
<xp:td
style="width:100px">
<xp:inputText
value="#{document1.computerName}"
id="computerName1">
</xp:inputText>
</xp:td>
<xp:td
style="width:20px">
</xp:td>
<xp:td>
<xp:message
id="message2"
for="computerName1" />
</xp:td>
</xp:tr>
</xp:table>
</xe:formRow>
<xe:formRow
id="formRow3"
labelPosition="none"
rendered="false">
</xe:formRow>
<xe:formRow
id="formRow4"
labelPosition="none"
rendered="false">
</xe:formRow>
</xe:formTable>
</xe:widgetContainer>
</xp:panel>
</xp:panel>
<xp:panel>
<xe:widgetContainer
id="widgetContainer1">
<xp:panel>
<xp:viewPanel
rows="30"
id="viewPanel1"
var="thisEntry">
<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="(dbAllRpPCTasks)">
<xp:this.keys><![CDATA[#{javascript:document1.getItemValueString("ID")}]]></xp:this.keys>
</xp:dominoView>
</xp:this.data>
<xp:viewColumn
columnName="title"
id="viewColumn5"
displayAs="link">
<xp:viewColumnHeader
value="Title"
id="viewColumnHeader5">
</xp:viewColumnHeader>
<xp:eventHandler
event="onclick"
submit="false"
refreshMode="partial"
refreshId="panelDig">
<xp:this.action><![CDATA[#{javascript:viewScope.UNID = thisEntry.getDocument().getUniversalID();
viewScope.parUNID = thisEntry.getDocument().getItemValueString("PCTaskParentUNID");
getComponent('dialog1').show()}]]></xp:this.action>
</xp:eventHandler>
</xp:viewColumn>
</xp:viewPanel>
<xp:panel
id="panelDig">
<xp:this.data>
<xp:dominoDocument
var="document2"
formName="PCTask"
action="editDocument"
documentId="#{javascript:viewScope.parUNID}">
</xp:dominoDocument>
<xp:dominoDocument
var="document3"
formName="rspPCTask"
action="editDocument"
documentId="#{javascript:viewScope.parUNID}">
</xp:dominoDocument>
</xp:this.data>
<xe:dialog
id="dialog1"
style="width:700px;height:600px"
refreshOnShow="true">
<xp:table>
<xp:tr>
<xp:td>
<xp:label
value="Master Title"
id="label2" />
</xp:td>
<xp:td>
<xp:text
escape="true"
id="computedField4"
value="#{document2.title}">
</xp:text>
</xp:td>
</xp:tr>
<xp:tr>
<xp:td>
<xp:label
value="Master Task Notes"
id="label3" />
</xp:td>
<xp:td>
<xp:text
escape="true"
id="computedField5">
<xp:this.value><![CDATA[#{javascript:var tmpDoc:NotesDocument = database.getDocumentByUNID(viewScope.parUNID)
tmpDoc.getItemValueString("notes")}]]></xp:this.value>
</xp:text>
</xp:td>
</xp:tr>
<xp:tr>
<xp:td>
<xp:label
value="Master Attachments"
id="label5" />
</xp:td>
<xp:td></xp:td>
</xp:tr>
<xp:tr>
<xp:td></xp:td>
<xp:td></xp:td>
</xp:tr>
<xp:tr>
<xp:td>
<xp:label
id="label7"
value="Notes" />
</xp:td>
<xp:td>
<xp:inputTextarea
id="inputTextarea1"
style="width:98.0%;height:100px"
value="#{document3.notes}">
</xp:inputTextarea>
</xp:td>
</xp:tr>
</xp:table>
</xe:dialog>
</xp:panel>
</xp:panel>
</xe:widgetContainer>
</xp:panel>
</xp:panel>
<xp:eventHandler
event="onClientLoad"
submit="true"
refreshMode="norefresh">
<xp:this.script><![CDATA[try {
dojo.byId("#{id:employeeName1}").focus();
} catch (e) { }]]></xp:this.script>
</xp:eventHandler>
</xp:view>
To show all rich text field's attachments of "another" document in a fileDowndload control:
add a panel around your fileDownload control,
add a dominoDocument data source to the panel
set attribute documentId to "another" document's UNID
set fileDownload's value to document's rich text field
(in your case the rich text field is called "attachments")
<xp:td>
<xp:panel>
<xp:this.data>
<xp:dominoDocument
var="documentPCTaskParent"
action="openDocument">
<xp:this.documentId><![CDATA[#{javascript:
document.getItemValueString("PCTaskParentID")
}]]></xp:this.documentId>
</xp:dominoDocument>
</xp:this.data>
<xp:fileDownload
rows="30"
id="fileDownload1"
displayLastModified="false"
value="#{documentPCTaskParent.attachments}">
</xp:fileDownload>
</xp:panel>
</xp:td>
BTW tmpDoc.getAttachment("attachments") you used doesn't return all attachments of rich text field "attachments" but would look for an attachment with the file name "attachments" somewhere in document.
I would avoid the file download control if possible. What you likely want to do is just build html links or images to the actual files themselves. So it's mostly a matter of figuring out the correct URL to get to it. Typically these are old school "non XPages" URL's... the classic domino stuff.
Everything I know about doing this I learned form this post: http://www.wissel.net/blog/d6plinks/SHWL-86QKNM
Short answer: you can add tmpDoc as a true document data source (using
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.
I have 3 comboboxes
Combo1
Combo2
Combo3
If Combo1 is blank (no selection) then combo2 is hidden. If Combo2 is blank then Combo3 is hidden.
If Combo1 is changed, it blanks Combo2, if Combo2 is changed it blanks Combo3.
This is because Combo2 choices are determined by Combo1 and Combo3 choices by Combo2. This is all working well.
What is happening if I change Combo1 then Combo2 and Combo3 are being blanked just as expected but Combo3 is not being hidden. If all I do is change Combo1 again, Combo3 is hidden. It is almost like I need 2 update events.
Is there any way around this?
Update
The issue seems to be with comboboxes that have computed selection values. In the sample below, changing the State should cause the ShowRoom scope variable to be "0" Changing Floor sets it to "1". A Computed Field will show the current value of the scope variable. It appears the onChange event of the State combo box is not being triggered. If you change the city selection from computed to static values then it works fine.
Not Working (Computed Selections)<xp:table style="width:100%" id="tblSurvey2">
<xp:tr>
<xp:td style="width:300px">
<xp:label value="*State" style="width:66.0px" styleClass="FieldLabel" id="label1">
</xp:label>
</xp:td>
<xp:td style="width:745.0px">
<xp:comboBox id="comboBoxState2" style="width:173.0px">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="tblSurvey2">
<xp:this.action><![CDATA[#{javascript:viewScope.put("ShowRoom2","0");}]]></xp:this.action>
</xp:eventHandler>
<xp:selectItem itemLabel="AL"></xp:selectItem>
<xp:selectItem itemLabel="CA"></xp:selectItem>
<xp:selectItem itemLabel="NY"></xp:selectItem>
<xp:selectItem itemLabel="PA"></xp:selectItem>
</xp:comboBox>
State =
<xp:text escape="true" id="computedField1">
<xp:this.value><![CDATA[#{javascript:getComponent("comboBoxState2").getValue()}]]></xp:this.value>
</xp:text>
Show Room =
<xp:text escape="true" id="computedField4">
<xp:this.value><![CDATA[#{javascript:viewScope.get("ShowRoom2");}]]></xp:this.value>
</xp:text>
</xp:td>
</xp:tr>
<xp:tr id="tr1">
<xp:td style="width:300px">
<xp:label value="*City" style="width:66.0px" styleClass="FieldLabel" id="label2">
</xp:label>
</xp:td>
<xp:td style="width:785.0px">
<xp:comboBox id="comboBoxCity2" style="width:175.0px">
<xp:eventHandler event="onclick" submit="true"
refreshMode="norefresh" id="eventHandler1">
</xp:eventHandler>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="tblSurvey2" id="eventHandler2"></xp:eventHandler>
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:new Array(getComponent("comboBoxState2").getValue() + " City1", getComponent("comboBoxState2").getValue() + " City2", getComponent("comboBoxState2").getValue() + " City3");}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</xp:td>
</xp:tr>
<xp:tr id="tr2">
<xp:td style="width:300px">
<xp:label value="*Floor" style="width:66.0px" styleClass="FieldLabel" id="label3">
</xp:label>
</xp:td>
<xp:td style="width:745.0px">
<xp:comboBox id="comboBoxFloor2" style="width:89.0px">
<xp:eventHandler event="onclick" submit="true" refreshMode="norefresh" id="eventHandler5">
</xp:eventHandler>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="tblSurvey2" id="eventHandler7">
<xp:this.action><![CDATA[#{javascript:viewScope.put("ShowRoom2","1");}]]></xp:this.action>
</xp:eventHandler>
<xp:selectItem itemLabel="Floor1"></xp:selectItem>
<xp:selectItem itemLabel="Floor2"></xp:selectItem>
<xp:selectItem itemLabel="Floor3"></xp:selectItem>
</xp:comboBox>
</xp:td>
</xp:tr>
<xp:tr id="tr3">
<xp:this.rendered><![CDATA[#{javascript:viewScope.get("ShowRoom2") == "1";}]]></xp:this.rendered>
<xp:td>
<xp:label value="*Room" style="width:66.0px" styleClass="FieldLabel" id="label6">
</xp:label>
</xp:td>
<xp:td>
<xp:comboBox id="comboBoxRoom2" style="width:89.0px">
<xp:selectItem itemLabel="A"></xp:selectItem>
<xp:selectItem itemLabel="B"></xp:selectItem>
<xp:selectItem itemLabel="C"></xp:selectItem>
</xp:comboBox>
</xp:td>
</xp:tr>
</xp:table>
<xp:br></xp:br>
<xp:br></xp:br>
I presume you are using partial refresh to do this?
So you have
C1 -> C2/C3
C2 -> C3
Since you only can have one partial refresh target you need to wrap C2/C3 into a panel and target that one for C1's partial refresh. Also check how you hide C3. you might want to use a viewScope variable to manage the states and depend your visibility on that one.
Update: You should bind your fields to viewScope variables, not set extra values. Also: a combobox shows when the bound variable value is missing or has no match the first value, but doesn't reflect it. So in a combobox you always need to have a first value that makes sense "-Please select|-" is common or looking up the actual first value. In your case the "please select" makes sense. You also might consider if you really want to hide the fields (that becomes a "mystery meat" navigation) or just update the possible selections (remove the rendered properties from the example below to see how it works).
Here you go:
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:table style="width:100%" id="tblSurvey2">
<xp:tr>
<xp:td style="width:300px">
<xp:label value="*State" style="width:66.0px"
styleClass="FieldLabel" id="label1">
</xp:label>
</xp:td>
<xp:td style="width:745.0px">
<xp:comboBox id="comboBoxState2" style="width:173.0px"
value="#{viewScope.selectedState}">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="tblSurvey2" id="eventHandler2">
<xp:this.action><![CDATA[#{javascript:viewScope.selectedCity = "-";
viewScope.selectedFloor = "-";
viewScope.selectedRoom = "-";}]]></xp:this.action>
</xp:eventHandler>
<xp:selectItem itemLabel="-Please select-"
itemValue="-" id="selectItem1">
</xp:selectItem>
<xp:selectItem itemLabel="AL" itemValue="AL" id="selectItem2"></xp:selectItem>
<xp:selectItem itemLabel="CA" itemValue="CA" id="selectItem3"></xp:selectItem>
<xp:selectItem itemLabel="NY" itemValue="NY" id="selectItem4"></xp:selectItem>
<xp:selectItem itemLabel="PA" itemValue="PA" id="selectItem5"></xp:selectItem>
</xp:comboBox>
</xp:td>
</xp:tr>
<xp:tr id="tr1" style="background-color:rgb(253,250,227)">
<xp:this.rendered><![CDATA[#{javascript:viewScope.selectedState && (viewScope.selectedState != "-")}]]></xp:this.rendered>
<xp:td style="width:300px">
<xp:label value="*City" styleClass="FieldLabel"
id="label2">
</xp:label>
</xp:td>
<xp:td style="width:785.0px">
<xp:comboBox id="comboBoxCity2"
value="#{viewScope.selectedCity}">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" id="eventHandler1" refreshId="tblSurvey2">
<xp:this.action><![CDATA[#{javascript:viewScope.selectedFloor = "-";
viewScope.selectedRoom = "-";}]]></xp:this.action>
</xp:eventHandler>
<xp:selectItems id="selectItems1">
<xp:this.value><![CDATA[#{javascript:var hasState = viewScope.selectedState && (viewScope.selectedState != "-");
var result = ["-Please select-|-"];
var cities = viewScope.selectedState + " " + ["City1","City2","City3"];
for (var x in cities) {
result.push(cities[x]);
};
return hasState ? result : "Please select a state first|-";
}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</xp:td>
</xp:tr>
<xp:tr id="tr2">
<xp:this.rendered><![CDATA[#{javascript:viewScope.selectedCity && (viewScope.selectedCity != "-")}]]></xp:this.rendered>
<xp:td style="width:300px">
<xp:label value="*Floor" style="width:66.0px"
styleClass="FieldLabel" id="label3">
</xp:label>
</xp:td>
<xp:td style="width:745.0px">
<xp:comboBox id="comboBoxFloor2"
value="#{viewScope.selectedFloor}">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" id="eventHandler5" refreshId="tblSurvey2">
<xp:this.action><![CDATA[#{javascript:viewScope.selectedRoom = "-";}]]></xp:this.action>
</xp:eventHandler>
<xp:selectItems id="selectItems2">
<xp:this.value><![CDATA[#{javascript:var hasCity = viewScope.selectedCity && (viewScope.selectedCity != "-");
var result = ["-Please select-|-"];
var floors = viewScope.selectedCity + " " + ["Floor1","Floor2","Floor3"];
for (var x in floors) {
result.push(floors[x]);
};
return hasCity ? result : "Please select a city first|-";
}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</xp:td>
</xp:tr>
<xp:tr id="tr3" style="background-color:rgb(253,250,227)">
<xp:this.rendered><![CDATA[#{javascript:viewScope.selectedFloor && (viewScope.selectedFloor != "-")}]]></xp:this.rendered>
<xp:td>
<xp:label value="*Room" style="width:66.0px"
styleClass="FieldLabel" id="label6">
</xp:label>
</xp:td>
<xp:td>
<xp:comboBox id="comboBoxRoom2"
value="#{viewScope.selectedRoom}">
<xp:selectItems id="selectItems3">
<xp:this.value><![CDATA[#{javascript:var hasFloor = viewScope.selectedFloor && (viewScope.selectedFloor != "-");
var result = ["-Please select-|-"];
var rooms = viewScope.selectedFloor + " " + ["Room A","Room B","Room C"];
for (var x in rooms) {
result.push(rooms[x]);
};
return hasFloor ? result : "Please select a floor first|-"; }]]></xp:this.value>
</xp:selectItems>
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="computedField4" id="eventHandler3">
</xp:eventHandler>
</xp:comboBox>
</xp:td>
</xp:tr>
<xp:tr>
<xp:td>Current variables</xp:td>
<xp:td>State:
<xp:text escape="true" id="computedField1" value="#{viewScope.selectedState}">
</xp:text>
<xp:br></xp:br>
City:
<xp:text escape="true" id="computedField2" value="#{viewScope.selectedCity}">
</xp:text>
<xp:br></xp:br>
Floor:
<xp:text escape="true" id="computedField3" value="#{viewScope.selectedFloor}">
</xp:text>
<xp:br></xp:br>Room:
<xp:text escape="true" id="computedField4" value="#{viewScope.selectedRoom}">
</xp:text></xp:td></xp:tr></xp:table></xp:view>
You could simplify the code by moving the "please select" into its own value item and use a function rather repeating code, but you get the idea.
you can execute multiple partial updates with some javascript. Take a look at this:
http://xpageswiki.com/web/youatnotes/wiki-xpages.nsf/dx/Work_with_events_and_partial_or_full_refresh