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.
Related
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.
I want to create a generic action bar custom control with Save, Edit, Delete, ... buttons.
How can I pass var variable from xpage to a custom control?
Update
I successfully transferred document object to custom control and I can Save the changes made in document, but I can't delete it with same object.
Update:
<xp:this.action>
<xp:executeScript
script="#{javascript:compositeData.datasrc.save()}">
</xp:executeScript>
</xp:this.action>
Delete is not working:
<xp:deleteDocument
message="Do you want to delete?"
var="#{javascript:compositeData.datasrc}">
<xp:this.name><![CDATA[#{javascript:var page = sessionScope.get("prevview");
return (page=='')?'home.xsp':page}]]> </xp:this.name>
</xp:deleteDocument>
I tried also with:
var="#{javascript:compositeData.datasrc.getDocument()}">
but also didn't work.
When you define a custom control, you can specify control properties. These properties then show up in the property editor when you insert the custom control into an XPage or another control. You can specify the data type and allow them to repeat.
This is saver than to rely on scoped variables. Check Chris' introduction and the XPages 101 session or and many more for inspiration
You can do it for example with a Scoped Variable. If the variable value is specific to that XPage (and user) viewScope is probably the best.
The above options are the best way to do that, but keep in mind that if you define a variable in a scriptblock or somewhere else in the Xpage, you will be able to access this variable from your code in the CustomControl, too. I think that's because the XPage und the custom Controls are kind of merged when compiled. Keep that in mind, this can lead to very nasty problems, especially with recycling issues.
What is the purpose of this variable ? If its a variable to control which buttons are being shown it would be best to create properties for each button / section. These properties can be computed to either return true or false.
If you want to pass the code that a button should execute I would advice you to generate button bars for the most common locations ( aka actions ) and add custom buttons on the button bar by using a facet (Editable area its called in the designer) .On this facet you'll drag a panel on which the buttons are being placed.
I have an Xpages application that pulls data from another .nsf file. I have a view panel linked to a view in that db. The view has documents with several different forms in it. I want to be able to open each document in it's own form(xpage).
How do I write a computed At Runtime, open selected document using: statement that will select the correct Xpage to present the document.
If you use the Data View component instead of a View Panel, you can compute the pageName attribute, referencing the var attribute to return a different value for each row based on the document that row represents. The flexibility of the Data View component also makes it easier to make your app look more like a modern web application and less like an Excel spreadsheet. As an additional bonus, the mobile theme invokes a renderer that makes each Data View instance look like a native mobile list, so using Data Views instead of View Panels simplifies mobile development.
You have 2 options:
use "use xpage associated with form" and edit the form's property
use a SSJS formula to compute the Form. You provide a variable name in the view control var to access a view row as XSPViewEntry. If the Form is in a view column even one you don't display you use .getColumnValue otherwise getDocument.getItemValueString
Does that work for you?
Maybe this mothed can help you: Unable to get document page name for
Hope this helps
Mark
I had a similar problem today. I use only one form but 3 different xpages for associated with this form. I have 3 different document types in the view. I used rowData the get the type of the document.
try{
var v=rowData.getColumnValue("form");
if(v.indexOf("x")> -1){var page ="x.xsp"}
else if(v.indexOf("y") > -1){var page = "y.xsp"}
else{var page = "z.xsp"}
}catch(e){
var page = "x.xsp"
}
So to your view you can create a column with the value of the form and you can use it.
I have used the extension library Dynamic View control which has an event you can code to get a handle to the NotesViewEntry which was selected. See the demo database page Domino_DynamicView.xsp and the Custom Event Handler tab for an example.
Note, in 8.5.3 (I have not upgraded yet) if you add or edit the eventHandler for onColumnClick it will be added to the XPages source as an xe:eventHandler. It needs to be an xp:eventHandler to work. The way to do it is to copy the code in the source from the exiting event and delete it. Recreate the event and update the code. Then go back into the source and change the tags within the eventHandler to xp:.
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
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.