Clear an field on an Xpage? - xpages

On a XPage how can I clear some fields when a certain radio button is pressed?
The fields are on a panel. Outside of that panel are some radio buttons. In the onChange of the radio buttons I change the render property of the panel via a viewScope variable and a partial refresh of the panel to make it disappear. This works. I just want to be able to also blank out the fields as well, else the values are saved when the users submits!

The SSJS equivalent of the modifyField simple action is the setValue method of the document data source; for example:
currentDocument.setValue("fieldName", null);
If someone tells you to instead call getComponent("someId").setValue(null)... don't. At first glance, that also works, but it's less efficient, fragile, and doesn't work when the target component is in a repeat control but the event component is outside the repeat. Always update the data source directly... any components bound to that data source will automatically pick up any changes you make.

Add an event that will modify the field on onchange event and refresh the area you want to change.
<xp:modifyField
var="document1"
name="FIELDNAME"
value="">
</xp:modifyField>

Use client side onChange to run whichever of these dojo's, where the < parentID > is the id of the container the RadioButton or RadioGroup is within:
dojo.query("*[type=radio]:checked",dojo.byId(parentID)).forEach(function(node, index, nodelist){
node.checked=false;
});
dojo.query("*[type=checkbox]:checked",dojo.byId(parentID)).forEach(function(node, index, nodelist){
node.checked=false;
});
dojo.query("input",parentID).
forEach(function(node, index, nodelist){
node.value = "";
})
//reset(

Related

Xpages dojo dialog box selected values

I have dialog box using dojo, that is placed on top of the xpages view action to present user value from one of the view first column and then do the excel to export process. I also added XSP.addClientLoad fuctionality as well to get values user selected.
on OK button of dialog box, I have below code on client side javascript.
var d=dijit.byId('#{javascript:compositeData.dialogID}');
var SelectedValues = document.getElementById("#{id:SelectedValues}");
SelectedValues.value =d.getSelectedValues();
alert(d.getSelectedValues());
context.redirectToPage("excelExporter2.xsp",false)
Which saves the value of the existing selection of dialog box to session scope variable in hidden editable field of Custom control.
Is this correct approach to set scope varaibles ?, also I want to loop through categorized view based session scope variable and export them on xpages so aftr this I want to trigger SSJS which will take care of excel to import part.
So my final aim is that based on user selection of dialog box, I want to run excel to export functionality (which is ssjs ) so please help me how to get started from here to jump into SSJS and also my approach of setting session scope variable is appropriate ?
Do You have a part of code that has to be ran on client side? If not, try to write it on server side straight away. For example to do Export to Excel You could probably use "window.open('some_url')" rather than that.
Otherwise, You can use this trick to fire a SSJS event on XPage/Custom control:
Create an event somewhere on XPage. Make sure it has and ID property, and that the event name is something else than standard events (onChange, onClick). Put the server code in that event that You want to run.
<xp:eventHandler id="eventHandlerId" event="myEvent" submit="true"
refreshMode="partial" refreshId="refreshId">
<xp:this.action><![CDATA[#{javascript:peformSSJSAction();}]]></xp:this.action>
</xp:eventHandler>
Fire the event from client side Javascript.
XSP.allowSubmit();
XSP.firePartial(null, "eventHandlerId", "refreshId");
Parameter "refreshId" is the refresh ID of refreshed area during partial refresh after the code is done.

prevent validation while running XSP.partialRefreshPost

In an xpage I have two select2 lists. The choice in the first select box directs the options in the second select box.
The lists are defines via List Box controls.
In order to have select2 applied to them I have a scriptblock
$(document).ready(
function(){
x$("#{id:list1}").select2();
}
)
$(document).ready(
function(){
x$("#{id:list2}").select2();
}
)
$(document).ready(
function(){
x$("#{id:list1}").on("change", function(e) {
XSP.partialRefreshPost("#{id:pnlList2}"
})
pnlList2 contains the second list box.
The problem is that the validation for the second list is triggered when the first list box changes in value.
I tried to apply as parameters:
'params': {
'disableVal':'true'
}
but that does not work as desired.
anyone has a suggestion?
There are a couple of ways to go about it, but I prefer the most performing one, that is partial execution. Partial execution should be mandatory as a best practice.
What happens with your code is that you refresh a portion of your page while validating the whole of it. By doing this the second select gets caught without value.
I would define the onchange param for the combobox - not the event handler - so that the select2 will automatically pick up the event without declaring it through JavaScript later on as you do.
Just use:
<xp:combobox onchange=“XSP.partialRefreshPost('#{id:select2Id}', { execId: '#{id:select1Id}' }”
As I said select2 will see the onchange declared in this way and honor it. When it will fire only the combobox1 will be evaluated, thus automatically skipping any other validation on the page because not included. At this point the second select will not complain and be refreshed.
An additional word of advice is to reinitialize the second combobox with select2 because the partial refresh will destroy it. Better to expand the partial refresh area to include both the combobox and the scriptBlock specific for the second select.

How can we use ONLY client side script for "hide/whens"?

I am working on a large, worldwide application, which includes access from areas of low bandwidth. As such, I want to use a minimum of SSJS or partial refreshes for all the complex hide/when calculations. Here is what I have so far for a simple "hide/when":
A Yes/No radio button, with CSJS to show a panel ("Yes") or hide the
panel ("No").
The panel has a formTable inside it, and the values are shown or hidden, as per #1.
In the XPage's onClientLoad, the following code is run:
// "getRadioValue" is a simple script to return the value of a radio button
var v_value = getRadioValue("#{id:radioButton}");
v_div = '#{javascript:getClientId("radioButtonPanel")}';
// show or hide div simply use dojo to change the display of the panel
if (v_value == 'Yes') {
showDiv(v_div);
} else {
hideDiv(v_div);
};
For a new document, the onClientLoad script will hide the "radioButtonPanel" successfully. Changing the radio button to "Yes" will show the radioButtonPanel, just as clicking "No" will hide it. It works great! :-)
Once the document is saved and reopened in read mode, though, the onClientLoad CSJS event should read the saved value in the document, and decide to show the panel or not. When the document is opened in edit mode, the onClientLoad fires, reads the radioButton value and successfully shows or hides the panel.
This is what I've tried so far, to get it to work in read mode:
In CSJS, using "#{javascript:currentDocument.getItemValueString('radioButton'}" to get the value,
Doing some calculations in the "rendered" or "visible" properties, but that's SSJS and, if hidden, prevents any of the "show/hideDiv" CSJS visibility style changes.
Adding an old fashioned "div" to compute the style (which is what I used to do before XPages), but since I can't do pass-thru html any more, I can't seem to get a CSJS calculation for the style. Ideally, I can do something like this:
<div id="radioButtonPanel" style="<ComputedValue>">
Where the ComputedValue would read the back end value of the document, and decide to add nothing or "display:none".
Note that I don't want to use viewScopes, since this long form would need many of them for all the other hide/when's.
Is there any way to make this 100% CSJS? I feel like I'm very close, but I wonder if there's something I'm just missing in this whole process.
First, rather than computing style, I'd recommend computing the CSS class instead -- just define a class called hidden that applies the display:none; rule. Then toggling visibility becomes as simple as a call to dojo.addClass or dojo.removeClass.
Second, I see that you're using the #{id:component} syntax to get the client ID of the radio button but using SSJS to get the client ID of the panel. Use the id: syntax for both; this is still just a server-side optimization, but if there are many instances of these calculations, it adds up. Similarly, replace #{javascript:currentDocument.getItemValueString('radioButton'} with #{currentDocument.radioButton}. Both will return the same value, but the latter will be faster.
Finally, any attribute of a pass-thru tag (any component with no namespace, like xp: or xc:) can still be computed, but you'll need to populate the expression by hand, since the editor doesn't know which attributes for valid for these tags, and therefore doesn't provide a graphical expression editor. So if the ideal way to evaluate the initial display is by wrapping the content in a div, the result might look something like this:
<div class="#{javascript:return (currentDocument.getValue('radioButton') == 'Yes' ? 'visible' : 'hidden');}">
<xp:panel>
...
</xp:panel>
</div>

XPages remove documents on server and trigger partial refresh

I am struggling with the following.
On my XPage I have a viewpanel component, but it is not bound to a notesview datasource, but to a hashmap stored in viewScope. Reasons for this is beyond scope of my question.
Since the lines in my view are not actually linked to the documents I cannot use the standard checkboxes and the related getSelectedDocIds. I do however want a way to remove the selected documents. I have a column with checkboxes containing the unid of the corresponding row.
So long story short. I have an array of unids and want to perform an action that does the following:
Display a dijit.Dialog asking for confirmation
If OK clicked call a function that does the following:
Remove the documents based on the unids
Refresh the viewpanel
I am thinking of the following 2 solutions, but in doubt what would be best (maybe a third, even simpler solution?)
Have the OK button of the dojo dialog call a function that does an XmlHttpRequest to an XAgent or plain old LS agent
Have the OK button trigger an eventhandler that runs on the server as described by JeremyHodge here. But how would I pass the unids as parameter and refresh the view afterwards?
Thanks!
Cant you just make use of the extension library dialog with the dialog button control. In this button control you can then
A third option would be to add a column to your datatable/view which contains checkboxes. On the onchange event of these boxes you add an eventhander which adds the value to a viewScope variable.
A button on the bottom (or top.) of the page you add the code you need to remove the selected items from the hashmap, delete the documents associate with the selected id's. this button can be a ordinary button with a partial refresh on the viewpanel. When you run into the bug that you cant use buttons in a dialog please use the extension library dialog control because this fixes that issue for you.
If the current user does not have the correct access level to delete documents you could use the sessionAsSigner global (assuming the signer of the design element has the correct access levels).
This way you dont need to go call an xAgent by xmlthttprequest and can stay with the default xpage methodology.
I hope this helps in some way
I would second #jjbsomhorst in the use of the extension library for the dialog box - if you use one at all. Usually users don't read dialog boxes. So the approach would be add the column with the checkboxes, but don't bother with an event handler, but bind them ALL with their value to ONE scopeVariable. On submission that variable will then hold an array with the selected UNID.
Then render a page that lists these documents and have a confirm button. While the new page affords a server round-trip the likelihood, that users actually pay attention is way higher. What you can do:
Have the normal page that renders the dialog with editable checkboxes and when the user clicks "Delete" you set something like viewScope.confirmDeleteMode=true; and use that as condition for the checkboxes and make them read-only AND set the class of the selected rows to "morituri" which in your CSS would have something like .morituri { color: white; background-color : red; font-weight: bold } and a new button "Confirm Delete" (and hide the Delete button).
This way you only have one page to deal with.
I went for option 2, which has the possibility to provide the partial refresh id. I passed the unids as a submitvalue like:
function doRemove(unids){
XSP.executeOnServer(ISP.UI.removeEventID, ISP.UI.removeRefreshID, {
params: {
'$$xspsubmitvalue': unids
},
onComplete : function() {
//alert('test')
}
});
}
The ISP.UI.removeEventID performs the following code:
var unids = context.getSubmittedValue();
removeDocuments(unids); //SSJS function performing the actual delete
viewScope.reload = 'reload' //triggers the hashmap to be rebuild based on new documentcollection

The buttons in a repeat don't hide/show after refreshing the panel the repeat is in?

I have a repeat that has buttons embedded in it. The repeat is in a panel. When the user clicks a button the button should hide/show (I partial refresh the panel). The repeat is tied to a Domino view and I see the other values that I from that view get updated in the repeat, so, it does not seem like a view index issue (I refresh the view index in my code.)
If I use context.reloadPage() in my button onclick code then the buttons will hide/show like they should, but, that seems like I am using a sledge hammer! Any suggestions on how to get the buttons to recompute the visible property when the panel that holds the repeat is rendered? Another strange thing is that the visible property gets computed three times whenever I refresh the panel that holds the repeat.
thanks, Howard
I think your looking for
getComponent("<id>").setRendered(true / false);
Hi For Repeat control's entry is used to make our head hard. Because handling the entry by SSJS, we can get the value and set the value. But rendering part, id of the repeating component are same for all. So if we try to give reder as false. It hides all of our repeating component.
Try to use the following., [Put this in button onclick, and see the value of below]
var entryValue= getComponent("repeat1").getChildren().get(0).getValue()
getComponent("inputText1").setValue(entryValue)
But in client side we can easily handle. Because the id of the DOM object is unique for all repeating component.
var id1="view:_id1:repeat2:"+'2'+":button1"
document.getElementById(id1).style.display="none"
This will hide the third entry of your repeat control component.
Please see the post, You may get better idea
Found a solution. My original solution was getting values from the repeat rows (using the collection object, which was a viewentrycollection and using getColumnValues) to compute the rendered property for the buttons.
Instead, I created a viewScope variable (a Vector) that holds the state of the buttons (which set of buttons to show). This gets populated in the beforePageLoad event of the page.
The button onclick code updates this viewScope variable after performing its processing. All works very nice now. I guess it was something in the JSF lifecycle that kept the buttons from being properly updated. Using the viewScope variable works fine.
With addition to what Ramkumar said, you can use the index variable in the repeat control to identify each and every occurrences inside the repeat control. You will get more idea, if you inspect with element from firefox[You might need firebug]. Usually the field mentioned inside a repeat control itself can be considered as an array

Resources