Hiding based on previous combo box choice in xpages? - xpages

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

Related

Button can be clicked only once on a XPage

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>

Looking for best approach for signature button on xpage

I need a simple button whereby a user clicks to sign off on a document. A single signer per document, but when they click it, it puts their name and the date in two visible fields, and changes the status field.
What is the best approach for this? This is probably drop-dead simple but for some reason I cannot get it working.
They have been forced to log in by this time.
Thanks in advance.
Matt
Try the following:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.data>
<xp:dominoDocument var="document1" formName="test"></xp:dominoDocument>
</xp:this.data>
<xp:panel id="panelMain">
<xp:table>
<xp:tr>
<xp:td colspan="2">
<xp:label value="Main Form" id="label1"></xp:label>
</xp:td>
</xp:tr>
<xp:tr>
<xp:td style="width:100.0px">
<xp:label value="Now" id="label2"></xp:label>
</xp:td>
<xp:td>
<xp:text escape="true" id="computedField1" value="${javascript:return #Now();}">
<xp:this.converter>
<xp:convertDateTime type="both"></xp:convertDateTime>
</xp:this.converter>
</xp:text>
</xp:td>
</xp:tr>
</xp:table>
</xp:panel>
<xp:panel id="panelSignature" style="background-color:rgb(192,192,192)">
<xp:button value="I Agree" id="button1">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="SignatureTable">
<xp:this.action><![CDATA[#{javascript:
document1.replaceItemValue("SignedDate",#Now());
document1.replaceItemValue("SignedBy",userBean.getDisplayName());}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:table id="SignatureTable">
<xp:tr>
<xp:td colspan="2">
<xp:label value="SignatureTable" id="label3"></xp:label>
</xp:td>
</xp:tr>
<xp:tr>
<xp:td style="width:100.0px">
<xp:label value="SignedBy" id="label6"></xp:label>
</xp:td>
<xp:td>
<xp:inputText id="computedField4" value="#{document1.SignedBy}" readonly="true"></xp:inputText>
</xp:td>
</xp:tr>
<xp:tr>
<xp:td style="width:100.0px">
<xp:label value="SignedDate" id="label5"></xp:label>
</xp:td>
<xp:td>
<xp:inputText id="computedField3" value="#{document1.SignedDate}" readonly="true">
<xp:this.converter>
<xp:convertDateTime type="both"></xp:convertDateTime>
</xp:this.converter>
</xp:inputText>
</xp:td>
</xp:tr>
</xp:table>
</xp:panel>
</xp:view>
Judging by this "They have been forced to log in by this time." your problem is in your ACL. Seems, you allow anonymous reading of the document, but in the moment you want to save it, ACL does not allow anonymous users to do that, so Domino asks for their identity.
Set anonymous access to No access level.
Here's a button, but if the user is not logged in and does not have anonymous edit access, then a login dialog will appear. For a signing function, I assume the user must be logged in to sign. document1 is the Xpage data document to be signed.
<xp:button
value="Sign"
id="button1"
styleClass="btn btn-primary">
<xp:eventHandler
event="onclick"
submit="true"
refreshMode="complete">
<xp:this.action>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:
document1.appendItemValue("SignerName", session.getEffectiveUsername();
document1.document1("SignedDate", session.createDateTime(#Now()));
document1.save();
}]]></xp:this.script>
</xp:executeScript>
</xp:this.action>
</xp:eventHandler>
</xp:button>
If you need to update a document without logging in, then in the button, you will have to get the doc with sessionAsSigner and then update.

Xpages display attachment in dialog box from another document

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

XPage - Refreshing Repeat control

I have button in a xpage which creates a document and refreshes a repeat control. All is working fine except the repeat control is showing the newly added document at the top of the table (IMG1).
But after refresh the xpage again, the repeat control renders the table properly (IMG2)
Repeat Code
<xp:panel>
<xp:table style="width:100.0%">
<xp:tr>
<xp:td style="font-weight:bold">
Hardware
</xp:td>
<xp:td style="font-weight:bold">
Quantity
</xp:td>
<xp:td style="font-weight:bold">
Asset Tag No
</xp:td>
<xp:td style="font-weight:bold">
Previous User
</xp:td>
<xp:td>
</xp:td>
</xp:tr>
<xp:repeat id="rpHardware" rows="30" var="clHardwares">
<xp:this.value>
<![CDATA[#{javascript:var docMain:NotesDocument = compositeData.docOnboarding.getDocument();
var vwApp:NotesView = database.getView("lkupHardwaresByParentID");
vwApp.getAllDocumentsByKey(docMain.getUniversalID(),true)}]]>
</xp:this.value>
<xp:tr>
<xp:td>
<xp:text escape="true" id="cfHWName">
<xp:this.value>
<![CDATA[#{javascript:clHardwares.getItemValueString("REQ_HW_Name")}]]>
</xp:this.value>
</xp:text>
</xp:td>
<xp:td>
<xp:text escape="true" id="cfHWQuantity">
<xp:this.value>
<![CDATA[#{javascript:clHardwares.getItemValueString("REQ_HW_Quantity")}]]>
</xp:this.value>
</xp:text>
</xp:td>
<xp:td>
<xp:text escape="true" id="cfHWAssetTagNo">
<xp:this.value>
<![CDATA[#{javascript:clHardwares.getItemValueString("REQ_HW_AssetTagNo")}]]>
</xp:this.value>
</xp:text>
</xp:td>
<xp:td>
<xp:text escape="true" id="cfHWPreviousUser">
<xp:this.value>
<![CDATA[#{javascript:clHardwares.getItemValueString("REQ_HW_PreviousUser")}]]>
</xp:this.value>
</xp:text>
</xp:td>
<xp:td>
<xp:link escape="true" text="Edit" id="link4">
<xp:eventHandler event="onclick"
submit="true" refreshMode="complete">
<xp:this.action>
<![CDATA[#{javascript:viewScope.put("selHardware",clHardwares.getNoteID());
getComponent("dlgAddHardware").show();}]]>
</xp:this.action>
</xp:eventHandler>
</xp:link>
<xp:link escape="true" id="link5" text="Delete">
</xp:link>
</xp:td>
</xp:tr>
</xp:repeat>
</xp:table>
</xp:panel>
Have you tried setting the repeat's "removeRepeat" property to TRUE? This removes unwanted div controls created from the repeat after the control's job is done.
(repeat >> All Properties >> basics)
EDIT:
forgot to mention that your button cannot perform a partial refresh on the repeat itself if that property is set to TRUE. Instead give your surrounding table or an aditional panel its own id which you can use to perform the necessery update
Did you refresh your view after creating the new document?
database.getView("ViewName").refresh();

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