How to add an onComplete event to the Xpages extLib valuePicker control - xpages

I have an extensionLibrary valuePicker control on my XPage and I'd like to run some search code after user selection. How can I achive this. Any onComplete events? I'd like to omit an "onchange" event at the target field (user may change it manually and then I'd like to start search on Enter or Search Button click)
<xe:valuePicker id="valuePicker1"
for="TargetField" pickerText="Select"
dialogTitle="Select">
<xe:this.dataProvider>
<xe:simpleValuePicker labelSeparator="|">
<xe:this.valueList><![CDATA[#{javascript:getMyValues()}]]></xe:this.valueList>
</xe:simpleValuePicker>
</xe:this.dataProvider>
</xe:valuePicker>

From the source code, it looks like the Value Picker calls XSP.selectValue() passing in the dojoType of the dialog to show, by default extlib.dijit.PickerList. It's triggering an AJAX request to retrieve the values, but opening and closing the dialog is done via CSJS only. So there's no onComplete event like partial refresh. And there's no current hook to add CSJS to run when closing. But it would be possible to extend that JavaScript file and trigger that instead. I'm not sure in your use case what corresponding code you would then need for your Edit Box control.
My preferred method is to use the Dojo List Text Box to hold the selected values (rather than an Edit Box or other manually editable component), then use an onChange event on that target field. Personally I feel it gives a better user experience, discourages manual typing and avoids needing to validate the Edit Box for user input.

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.

Open an XPage from the Application Layout Banner

I'm using the Application Layout control and have set up a basicLeafNode within the bannerUtility links. I wanted to open another XPage (MeineAnmeldung.xsp) whenever that link 'Meine Anmeldungen' is clicked.
<bx:this.bannerUtilityLinks>
<xe:basicLeafNode
label="Meine Anmeldungen">
<xe:this.rendered><![CDATA[#{javascript:context.getUser().getRoles().contains('[CreateAnmeldung]')}]]></xe:this.rendered>
<xe:this.onClick><![CDATA[#{javascript:context.redirectToPage("MeineAnmeldungen.xsp")}]]></xe:this.onClick>
</xe:basicLeafNode>
but, as I have discovered, the onCLick event on the basicLeafNode is strictly CSJS, which I assume is the reason why I'm having issues.
Am I trying to do this at the wrong place? To be honest, I don't understand the difference between all these different bars at the top: Placebar, Search Bar, Title Bar, mastHeader. No idea which does what, and I'm trying to have a very simple UI without any clutter.
Or is there a way to redirect using CCJS? Perhaps by recalculating an URL, which I also am not sure about how to calculate.
Use a pageTreeNode instead. Here's an example:
<xe:this.bannerUtilityLinks>
<xe:pageTreeNode label="Meine Anmeldungen" page="/MeineAnmeldungen.xsp.xsp"></xe:pageTreeNode>
</xe:this.bannerUtilityLinks>
You can redirect via CSJS using location.href=.... CSJS is all the onClick event of the basicLeafNode can do.
The Application Layout control itself has an onItemClick event on the Events tab. That will allow you to trigger SSJS and use context.getSubmittedValue() to check the submitValue property (you'll need to add that) for the basicLeafNode.
See TitleBar tabs in ApplicationLayout control (extlib) generating invalid code

How can I know what form control had focus when ribbon button pressed?

Have a custom JS function that gets called when a ribbon button is pressed in the context of a form. In my custom JS function I need to know what form field had the focus just prior to the ribbon button being pressed. I've tried 2 ways (below) without success. Is there any way to do this reliably?
Way #1
According to this, I can get the control I want passed as a parameter to my JS. I've tried using both PrimaryControlId and PrimaryControl parameters.
<JavaScriptFunction FunctionName="OnCustomBtnFunc"
Library="$webresource:myJSfile.js">
<CrmParameter Value="PrimaryControlId" />
<CrmParameter Value="PrimaryControl" />
</JavaScriptFunction>
For both, I get an object passed to OnCustomBtnFunc() but it does not seem to enable me to determine which form control had the focus prior to the ribbon button being pressed.
Way #2
I call Xrm.Page.ui.getCurrentControl(). This works for form fields of some types but not others e.g. if it is a string field it works but I get null for a lookup.
you won't like this answer, but you can use JQuery to quickly grab every Control in your Form and assign it an OnBlur event. This event can either assign the ID or the control itself to global variable, which you will make accessible to your ribbon (which fires from a different scope).
People do not like this approach because of the different context scopes of the variables and because it involves playing with "unsupported" features of plain HTML. However, if you ask only the question "how" and not "should we", then this is an easy way for "how" you would do this.

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

client message after SSJS routine how?

I have a Button that in SSJS send and Email...
Now I would if is possibile show the status of sending of email in real-time to the user:
sending process....
sending Successful or sending error
How Can i call a JS client codice from SSJS routine?
Have you any suggest?
If you are using ExtLib then you can also use the #WarningMessage('messageText') method.
You will need to add a section to the XPage to display the messages. It can be as simple as
<xp:messages id="messages1"></xp:messages>
Once added each call to #WarningMessage will add a line to the messages pane.
8.5.3 introduced a very nice approach:
view.postScript
you may insert any CSJS code you like from the SSJS code.
This is quite straightforward.
1. Add a Hidden Input control on your page, noting the id.
2. In your SSJS use getComponent("inputHidden1").setValue("This is the message")
3. Ensure the Hidden Input control is in the area being refreshed (otherwise the value doesn't get passed back to the browser, so can't be accessed in CSJS)
4. Go to the Source pane and place the cursor on or in the eventHandler that is triggering your SSJS. You need to do this to get to the onComplete event
5. In All Properties panel go to onComplete, add your CSJS there. e.g. alert(dojo.byId("#{id:inputHidden1}").value)
This will run your SSJS and on completion alert the user with whatever code is in the field.
For a demo and demo code, check out my blog post: http://www.intec.co.uk/xpages-calling-client-side-javascript-from-server-side-javascript/
Another way to do it besides Pauls answer is to use a dialog from the extlib, and you can call it from ssjs, put a field in a dialog and set it to a scope value and show the dialog.

Resources