Select all items in checkbox group with CSJS? - xpages

I am able to select all of the items in a checkbox group with SSJS by simply setting the component's value.
But how would I do this in CSJS?

Assuming that the name of your check box group is checkBoxGroup this code snippet of check all checkbox should do the trick for you.
<xp:checkBox text="Check all" id="chkCheckAll">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[dojo.query("input[name=\"#{id:checkBoxGroup}\"]").forEach(
function(node) {
node.checked = document.getElementById("#{id:chkCheckAll}").checked;
}
)]]></xp:this.script>
</xp:eventHandler>
</xp:checkBox>

You select them with dojo.query and set the selected property to true. You need to check: every box will have its own ID, but the beginning of it is the same -or- you use a class. Or you look for the first and then select all siblings.
The strategy depends on your application's needs.
Check the dojo.query documentation for your options.

this is how you do it in jquery
$("[name$=checkBoxGroup1]").attr("checked",true)

Simplifying Naveen's answer, this worked great for me:
dojo.query("input[name=\"#{id:checkBoxGroup1}\"]").forEach( function(node) {
node.checked = true;
});

Related

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")
}

XPages custom validator

Ultimately I need to do some cross field validation and thought I would use a custom validator to do this. But I can't even get a simple example to work. The following code (which is pretty similar to that on p.116 of "Mastering XPages" allows any value (including an empty field). Am I missing something obvious?
<xp:inputText
id="field1"
value="#{document1.field1}">
<xp:this.validators>
<xp:customValidator>
<xp:this.validate><![CDATA[#{javascript:if (value == "") {
return new javax.faces.application.FacesMessage("Please enter a value");
}}]]></xp:this.validate>
</xp:customValidator>
</xp:this.validators>
</xp:inputText>
It is not possible to validate an empty field with a validator. A validator runs only if a value exist. In XPages you have the required property for fields which allows to check for empty fields; this is a workaround for this problem, and it is (as far as I know) not possible to create your own "required" validator.
If you want to create your own one, you have to create a converter instead
UPDATE 21.06.2013
It is possible to create an own required validator with a small workaround: http://hasselba.ch/blog/?p=764
You need to return a string with the error message in it - and not a FacesMessage object.
So in your case, do this instead:
<xp:inputText id="field1" value="#{document1.field1}">
<xp:this.validators>
<xp:customValidator>
<xp:this.validate><![CDATA[#{javascript:
if (value == "") {
return "Please enter a value";
}
}]]></xp:this.validate>
</xp:customValidator>
</xp:this.validators>
</xp:inputText>

How do you make a computed field both computed and databound to a field?

I know how to bind a computed field to a document field. And I know how to use javascript to compute a computed field. But how do I do both?
Say my javascript in the computed field is:
#Name("[ABBREVIATE]" ,#UserName());
How do I bind that to say document1.ReqName field?
I use two fields:
a hidden input field that computes the required value (using the xp:inputHidden control). I use "default value" to emulate Computed when composed - and converters to emulate Computed (inspired by Tommy Valand).
a visible computed field or a visible input field set to read only that does the same calculation. Perhaps this can be changed to display the value of the hidden input field using getComponent("").getValue()?
Maybe I miss the Point but why don't You simply do the following?
<xp:inputText id="inputText1" value="#{document1.Reader}">
<xp:this.defaultValue>
<![CDATA[#{javascript:#Name("[ABBREVIATE]",#UserName());}]]>
</xp:this.defaultValue>
</xp:inputText>
This is a Textfield bound per EL to the DocumentField. If the field is empty it is calculated by the default value.
Great! - I missed the point. But You can try this one:
<xp:text escape="true" id="computedField3">
<xp:this.value>
<![CDATA[#{javascript:
if(#IsNewDoc()){
document1.replaceItemValue("Reader",#Name("[ABBREVIATE]",#UserName()));
}
return document1.getItemValue("Reader");}]]>
</xp:this.value>
</xp:text>
For the computed field's Value, use Advanced data binding and select Expression Language (EL).
The expression to use is simply "document1.ReqName" (no quotes).
I wouldn't bind in this case. I would bind every other control and in this case manually add that into the document field directly with script before the save action.
so something like: (forgive the code not at my work comp)
<eventhandler>
<actionGroup>
<script><![CDATA[#{javascript:
doc.replaceItemValue("ReqName", #Name("[ABBREVIATE]" ,#UserName()));
}]]><script>
<saveDocument></saveDocument>
</actionGroup>
</eventhandler>
<xp:text escape="true" id="computedFieldTest1">
[CDATA[#{javascript:
var userName = "Username: "+("Reader",#Name("[ABBREVIATE]",#UserName()));
currentDocument.replaceItemValue("computedFieldTest1",userName);
return userName;
}]]></xp:this.value>
</xp:text>

Set focus to field using SSJS in 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>

Resources