Set focus to field using SSJS in Xpages? - xpages

I am validating my form using SSJS from a submit button. To display the error to the user I am using the extension library dialog box.
How can I set the focus to the field failing validation, using SSJS?
One thing I might be able to do is use CSJS in the OK button of the dialog box. I close it with the OK button as follows:
var errorField = '#{javascript:viewScope.get("errorField")}';
I tried the following but it does not seem to work.
if (errorField != null && errorField != "")
{
var ef = document.getElementsByName("#{id:" + errorField + "}");
ef.focus();
}
I am setting the scope variable errorField when I do the actual validation.

Yes my bad on the missing colon. Ok tried it out and it doesn't seem to be working for me either when I break up the id expression.
you have a viewScope set to the id of the error field, is it possible for you to set that to :
getComponent('...').getClientId();
if you could do that the you would be able to run:
var errorField = '#{javascript:viewScope.get("errorField")}';
var ef = dojo.byId(errorField);
ef.focus();
that works fine for me.

try using:
var ef = dojo.byId('#{id'+errorField+'}');
ef.focus();
getElementsByName is looking for multiple elements with name="..." and returns an array. you can't set focus to an array of controls.
where as in XPages all controls have unique id's, so using dojo to search for ids will return a single element

Try to set the focus after the partial (or full) refresh is done.
<xp:eventHandler event="onClientLoad" submit="false">
<xp:this.script><![CDATA[ var ef = dojo.byId('#{javascript:getClientId(viewScope.get("errorField"))}');
ef.focus();]]></xp:this.script>
</xp:eventHandler>

Related

Suitescript 2.0 Get Button on a sublist

I have an older Suitescript 1.0 user event script where on the BeforeLoad I change a label on a button in a sublist. (note this is a button on the sublist not on the main header of the form
In order to do that I did something like this:
function changePackageContentsButtonLabel(type, form, request)
{
var mySublist = form.getSubList('recmachcustrecord_tst_my_sublist');
if(mySublist != null)
{
var NewButton = mySublist .getButton('newrecrecmachcustrecord_tst_my_sublist');
if(NewButton != null)
{
NewButton .setLabel('New Label Text');
}
}
}
that worked fine in that i could find the button based on a call to the sublist.getButton
In 2.0 I was wondering how to do that.
I had thought i would call the getButton that is based off the context.form but it does not seem to find the button in that case. And though there are methods to addButton on a sublist, there does not appear to be a getButton on it. I know i could use JQuery but that may be a bit more brittle it seems.
In the Netsuite help section search for
SuiteScript 1.0 to SuiteScript 2.0 API Map
After you get the button object, use label property to get or set a value for the button label.
var myButton = form.getButton({
id : 'buttonid'
});
myButton.label = "New Label Text"
I ended up having to put the logic I wanted into a client script and called it off of the pageInit. What I had to do was use native javascript and locate the button (by document.ElementById() and when i got that element I was able to change the value. This was not the desired way but it seems that 2.0 does not allow you to locate a button on a sublist like 1.0 did.

beforePageLoad failing when a view column is computed

I've got a view control which opens an xpage. When the xpage opens, the beforePageLoad event fires. It checks to see if there are any attachments in a particular field of the document being opened and if there are, it returns list of the filenames. This was working fine. Then, I was asked to change what's displayed in one of the columns of the view. I added a variable to the view control's data section to access the row. I then added some javascript to the column to display the data differently. That worked and it displayed the data as wanted. However, when I now click on the link to open the xpage, when the beforePageLoad event fires, the code that's there now fails. It fails with this error at the starred line:
Script interpreter error, line=9, col=49: 'closureField' is null at
[/Function_ReturnListOfClosureAttachmentNames.jss].ReturnListOfClosureAttachmentNames(CCEB1351591847CB85257E7C005EF68C)
function ReturnListOfClosureAttachmentNames(ltDoc ){
var closureAttachmentFileNames = "";
var thisLT = ltDoc;
var closureField:NotesRichTextItem = thisLT.getFirstItem("closeAttachments");
*>>> var eos:java.util.Vector = closureField.getEmbeddedObjects();<<<
var eosi:java.util.Iterator = eos.iterator();
while (eosi.hasNext()) {
var eo:NotesEmbeddedObject = eosi.next();
closureAttachmentFileNames = closureAttachmentFileNames +","+eo.getName();
}
return closureAttachmentFileNames;
}
I call this function from the beforePageLoad event and pass it currentDocument.getDocument(). I think I might have lost the document context after changing the column display data from 'view column' to 'computed value' but I'm not sure. Any ideas would be appreciated.
thanks!
Clem
Figured it out: When I assigned a variable to the view, when you click on a linked column in that view, it loads the current ViewEntry into the context and not a current document. So I put the unid of the doc from the selected ViewEntry in an application scope variable and returned it to the Document Id property when I open the xPage. I have to now update all my views but there aren't too many luckily. Thanks for working through this with me!
Clem –

Changing multiple data in a view

I need help using Xpages. If there vas a question like this or there is an example can you tell me where to find it.
I have a main page that contains several rows and columns, like this
[Checkbox][Column1][Column2][Column3][Column 4][Column 5]
[Checkbox][Data1][Data2][Data3][Data4][Data5]
[Checkbox][Data1][Data2][Data3][Data4][Data5]
[Checkbox][Data1][Data2][Data3][Data4][Data5]
[Checkbox][Data1][Data2][Data3][Data4][Data5]
[Checkbox][Data1][Data2][Data3][Data4][Data5]
Now Data 5 is a default value and it is Undefined, the only values other that it can be set is to „Do“ or „Do not“. Is there a way to Chek several rows for which i vant to change the value to Do or Do not in Data 5 using combobox and save button, without going into detail view of the data.
For example, i have 30 rows that have Data 5 set to undefined, and i want 10 of them to set to Do. I just chek them in checkbox, select in combobox Do and press Save. So i don't have to endet evry row and edit them one by one.
Adapt the XSnippet Simple "Trash" Folder c/w Selectable Rows & Restore Functionality to your needs.
<xp:comboBox
id="comboBox1"
value="#{viewScope.DoOrDont}">
<xp:selectItem itemLabel="Do"></xp:selectItem>
<xp:selectItem itemLabel="Do not"></xp:selectItem>
</xp:comboBox>
<xp:button id="button4" value="Change selected rows">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:
var vp1 = getComponent("viewPanel1");
if(null != vp1){
var dm:com.ibm.xsp.model.domino.DominoViewDataModel = vp1.getDataModel();
if(null != dm){
var idsIter = dm.getSelectedIds();
while(null != idsIter && idsIter.hasNext()){
var id = idsIter.next();
if(null != id){
var doc:NotesDocument = database.getDocumentByID(id);
if(null != doc){
doc.replaceItemValue("yourField", viewScope.DoOrDont);
doc.save();
}
}
}
}
}}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
The example contains a combobox where you can select "Do" or "Do not" and a button which sets this value to all selected documents.
Not sure I got the whole picture of your requirements, but here is one way to do it.
When you "tick" a checkbox, use the server side "onclick" event to set a sessionScope containing the noteid and include any value you want to update the document with. set the refresh id to the checkbox.
For each checkbox the user ticks, a new noteid is added to the sessionScope.
When the user is ready to save the changes using the save button, loop the unids in the sessionScope and update the documents in the background and clear the sessionScope
Using this approach you can also provide a "next" page that show all the documents in the scope and allow the user to confirm the save
you might also want to add a keepalive so the users scope is not discarded
The best way for that is to combine client side and server side code. Here is what I would do in this case :
Add a StyleClass to the checkboxes. In order to do so click on a checkbox, go to all properties and find StyleClass in the list. For example let's put this class name : myCheckboxClass. With this class name you will be able to retrieve easily all the checkboxes checked on the client.
Add also a custom attribute to the checkboxes that contains the unid of the document related to the row. To do so click on a checkbox, go to all properties again and find attr. Add a new attr called for example unid and compute its value to be the unid of the row. This attribute will allow you to know from the client to which document this checkbox is linked to.
Now on your save button, with a client side script, you can really easily get all the documents to modify with the following :
var documentsToUpdate = [];
var checkboxes = document.getElementsByClassName("myCheckboxClass");
for (var i = 0; i < checkboxes.length; i++) {
var checkbox = checkboxes[i];
if (checkbox.checked) {
documentsToUpdate.push[checkbox.getAttribute("unid")];
}
}
// Send the array, in a JSON format, to the server
return XSP.toJson(documentsToUpdate);
Now on your save button, with this time the server side script, retrieve the information from the client, and use the array of unids to change the value you want in the selected documents :
// Get the return value from the client
var jsonDocumentsToUpdate = context.getSubmittedValue();
// Change the JSON into an array
var documentsToUpdate = fromJson(jsonDocumentsToUpdate);
// Go through the array and update the documents
for (var i = 0; i < documentsToUpdate.length; i++) {
var doc:NotesDocument = database.getDocumentByUNID(documentsToUpdate[i]);
// DO YOUR CHANGES
doc.save();
}
Now you have everything to do what you need. You just have to check what the user chose in the combo box and to do the proper changes according to it. I think it's really important to learn this approach combining client side and server side code, that can be apply a lot in Xpages to do what you want quickly.

How do I compute the Selected property of a BasicLeafNode for a Dynamic Content Control - Updated 03/26/2014

I have created an XPage with the following: Started by creating a custom layout control using the Application Layout. I aded the layout control to the xpage and then dropped in a Dynamic Content Control. I configured the control as follows:
<xe:dynamicContent id="dynamicContent1" defaultFacet="GovernanceReviews"
useHash="true">
<xp:this.facets>
<xc:ccViewDocumentTemplates xp:key="DocumentTemplates"></xc:ccViewDocumentTemplates>
<xc:ccViewGovProcurementReviews xp:key="GovProcurementReviews"></xc:ccViewGovProcurementReviews>
<xc:ccViewGovRevReporting xp:key="GovRevReporting"></xc:ccViewGovRevReporting>
<xc:ccViewGovRevWOCompleted xp:key="GovRevWOCompleted"></xc:ccViewGovRevWOCompleted>
<xc:ccViewGovernanceReviews xp:key="GovernanceReviews"></xc:ccViewGovernanceReviews>
<xc:ccViewProfilesByType xp:key="ProfilesByType"></xc:ccViewProfilesByType>
<xc:ccViewProfilesWithTargetCompl xp:key="ProfilesWithTargetCompl"></xc:ccViewProfilesWithTargetCompl>
<xc:ccViewLastUpdated xp:key="LastUpdated"></xc:ccViewLastUpdated>
<xc:ccViewUserGuide xp:key="UserGuide"></xc:ccViewUserGuide>
<xc:ccViewTracking xp:key="Tracking"></xc:ccViewTracking>
</xp:this.facets>
</xe:dynamicContent>
Then I dropped in a navigator control in the left column and created BasicLeafNodes to correspond to the dynamic content control I used the href property and used the #content="" to display the correct content.
This works just fine, but I am having problems figuring out how to make the selections in the navigator highlight when they are selected. I know I need to compute the Selectd property,but I can't figure out how to get the xp:key value so I can compare it to the SubmitValue. I know this is probably something simple, but I can't figure it out.
Can someone please enlighten me.
Thanks,
MJ
ADDED 03/26/2014 - I have a feeling that it has something to do with Using the href property of the Dynamic Content Control to perform the content switching. I know that makes the BasicLeafNodes Links. So, not sure how the Navigator records which link is being executed and how to capture that.
MJ
Add a value is the submitValue property
And in the onItemClick Event
Assign the submitted value to a viewScope variable
viewScope.Selected=context.getSubmittedValue()
And finally check if the viewScope variable equals your item submit value in the selected property. This needs to be calculated
if(viewScope.Selected="byCategory"){
return true
}else{
return false
}
The following is working for me:
if(viewScope.Selected == "byCategory"){
return true
} else{
return false
}
An equality test must be made with two equal symbols (or three). One equal symbol evidently always returns true.
I did it by jQuery. Just put the following code to the custom control, which contains navigator.
$( function() {
if (window.location.hash.length > 0) {
select()
}
});
$(window).on('hashchange', function() {
select();
});
function select() {
$(".lotusColLeft .lotusMenu .lotusBottomCorner li").removeClass(
"lotusSelected")
$(".lotusColLeft .lotusMenu .lotusBottomCorner li a")
.filter(
function() {
return window.location.hash.indexOf($(this).attr(
'href')) > -1
}).parent().addClass("lotusSelected")
}

Setting value of a Radio Button Group Client Side

I need to set the value of a Radio Button Group that has two possible values. I'm able to accomplish this with SSJS, but having issues setting it via CSJS. Any help is appreciated.
I use something like this:
function setRadioValue(value)
{
var elements = document.getElementsByName ("#{id:radioGroup1}");
for(i=0;i<elements.length;i++) {
if (elements[i].value == value) {
elements[i].checked = true;
}
}
}
Then you can just call setRadioValue("This is teh value of the Radio Button I want to set")
Thanks
You need to get the the server-side generated name of the radio button group using the #{id:} method. Example:
var radioButtonGroup = XSP.getElementById("#{id:radioButtonGroupName}");
You can then use client-side Javascript to manipulate the radioButtonGroup element. I believe you need to loop over the radio buttons in the elements until you find the radio button with the desired value. You can then set its checked value to true.

Resources