XPages: ask a confirmation when saving and set a value if confirmed - xpages

I have a document that gets published using an xagent (that does all sorts of things to the document).
Before sending to the xagent, I would like to ask the user if he wants the effective date of the document to be set to today's date. For now, I don't have that field available in edit mode on the page, but I guess I'll need it.
The big question is how to ask a confirmation (do you want the date to be set to today?) and put the date in the field before actually saving the document and sending it to the xagent page. I already have some simple actions into that save button. Here is the code:
<xp:button value="Save and Publish" id="button6">
<xp:this.rendered><![CDATA[#{javascript:database.queryAccessRoles(session.getEffectiveUserName()).contains('[Admin]') && currentDocument.isEditable()}]]></xp:this.rendered>
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:actionGroup>
<xp:modifyField name="Status" var="pageDocument">
<xp:this.value><![CDATA[#{javascript:if(getComponent("publishLater1").getValue() == "1") {
return "Scheduled Publication";
} else {
return "To Be Published";
}}]]></xp:this.value>
</xp:modifyField>
<xp:saveDocument var="pageDocument">
</xp:saveDocument>
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript: //remove the lock doc
//unlockDoc(pageDocument.getDocument().getUniversalID());
//for scheduled publications, a LotusScript agent will do the work
var res=facesContext.getExternalContext().getResponse();
if(getComponent("publishLater1").getValue() == "0") {
// Now load the publish Agent
res.sendRedirect(#Left(facesContext.getExternalContext().getRequestContextPath(),".nsf")+".nsf/xPublish?OpenAgent&docid=" + pageDocument.getDocument().getUniversalID());
} else {
//send to the drafts view, to show it has the clock icon in the draft view
res.sendRedirect(#Left(facesContext.getExternalContext().getRequestContextPath(),".nsf")+".nsf/adminDrafts.xsp");
} }]]></xp:this.script>
</xp:executeScript>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
<i class="fa fa-newspaper-o pull-left fa-2x">
</i>
</xp:button>

You could do it several ways I'd think. If you're using the extension library you could use a dialogBox. so your save and publish button opens a dialog box with your question or even additional fields. Then you add a cancel button of course to the dialog box but also a "continue" button. That button accesses the fields if you put any in or knows that they want "today's" date and then that button calls the xagent passing in any appropriate parameters.

Presumably pageDocument is a dominoDocument datasource. A dominoDocument datasource is either all read only or all editable. And SSJS has access to that datasource. So add another executeScript action and you can modify whichever other field you want to as well.
What I'd recommend, though, is to skip the simple actions and do everything in script. The SSJS editor allows you to see all the methods available for a dominoDocument datasource. With a little knowledge of LotusScript or a little investigation, it should be obvious which method to use to replace an item value for the "Modify Field" simple action (quick tip, again go to the datasource rather than the publishLater1 component) and which method to save the document. If you start breaking away from simple actions and building your confidence in SSJS, it will give you greater flexibility in the long run.

Related

Confirmation Action - Confirmation text, computed value not dynamic?

on my xpage I have a button where I have made the confirmation text computed with SSJS:
<xp:button value="Queue" id="btnQueue"
styleClass="btn-primary">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action>
<xp:confirm>
<xp:this.message><![CDATA[#{javascript:return "Are you sure you want to change value from " + getComponent("From").value + " to " + getComponent("To").value + "?";}]]></xp:this.message>
</xp:confirm>
</xp:this.action></xp:eventHandler></xp:button>
I am using the same components to calculate the disable property. This works fine. Why not the computed text property?
Remember SSJS runs on the server, CSJS on the browser. #{javascript:....} means everything is being generated server-side and a literal message to the user is being passed to the browser, which will then be generated when the user clicks the button. So the "from" and "to" values are those that were on the server when it was last passed to the browser.
Don't use the simple action (which passes a server-side message to the browser). Use CSJS instead, confirm('My Message');. To get variable content from the current browser page into it, you need CSJS to retrieve the value from the relevant HTML element on the page, based on the ID. To use that, pass #{id:From} and #{id:To} into your preferred CSJS method for retrieving an element by ID.

How can I refresh the field in CSJS

How to refresh one field in csjs? the code is here:
<xp:repeat id="repeat1" rows="30" var="currentDetail" indexVar="detailIndex" value="#{LeaveBean.details}">
<xp:inputText id="leavefrom" value="#{currentDetail.subfromtime}">
<xp:eventHandler event="onblur" submit="false" refreshMode="partial" refreshId="repeat1">
<xp:this.script><![CDATA[
XSP.partialRefreshPost('#{id:view:_id1:repeat1:0:leavefrom}');
var detailIndex = document.getElementById("#{id:detailIndexText}").innerHTML;
myRPC.checkfromdate(detailIndex).addCallback(function(returnAlert){alert(returnAlert);});
]]></xp:this.script>
</xp:eventHandler>
</xp:inputText>
</xp:repeat>
what I want to do is call ssjs from csjs as you can see, but the strange thing to me is the click thing didn't work immediately, for example, when I first open the page, and click the input field, and enter "1" in it, it should be popup alert just when i left the field, but nothing happend, then I click this field again, and enter "2", then I left the field, but I just got the alert "1" on the secreen...sorry for my poor expressions...
so my question is I should refresh the field just when I left the field immediately, but why the XSP.partialRefreshPost not working? I tried to refresh repeat1, not working either
update 2015/06/13:
At last, I found view.postScript....so....
One obvious problem is the partialRefreshPost id won't work. You're combining #{id:...} which runs server-side to calculate the corresponding client-side ID. But the ID that you're passing is a client-side ID for the first row of the repeat. Even if that corresponded to a server-side component, you're trying to hard-code every row to map to a field in row 1 of the repeat ("repeat1:0").
Is there a reason for not using a normal partial refresh and using view.postScript in your SSJS to post CSJS back to the browser? You're triggering a partial refresh posting data back anyway. I'm not sure what the final line of your code is doing, but it seems like it's calling another server-side request to add a response. So the code seems to do two calls to the server, to trigger an alert. I don't know the design and what that subsequent rpc call is doing, but if it can be achieved in a single partial refresh, that would seem better.

Session Expiration Warning

I have an XPages app that is supposed to save the main doc (and do a couple of other things) when the user clicks a button on the dialog box. The dialog box is presented by a CSJS function which runs according to a setInterval command. The dialog box and all the programming that present it are on a Custom Control. I have no problem displaying the dialog box, but have been unable to come up with a way to save the underlying document. I have other dialog boxes on their respective XPages, and saving the doc with a click (and some SSJS) works fine, but the same process doesn't seem to work if the dialog box is on a CC. I have searched all over the web, including StackOverflow, and haven't been able to find just what I need. Any ideas as to what I am missing?
Here's the code from one of my more recent attempts:
<xp:button value="Continue" id="button1">
<xp:eventHandler event="onclick" submit="false" id="eventHandler1">
<xp:this.script>
<![CDATA[
if (intvlID2) {
clearInterval(intvlID2);
}
var b18 = dojo.query('[id$="button18"]')[0];
if (b18) {
b18.click();
} else {
location.reload(true);
}
XSP.closeDialog('#{id:WarningDialog}');
]]>
</xp:this.script>
</xp:eventHandler>
</xp:button>
As you can see, it clears the interval first, then looks for a button on the underlying form. I've been able to verify that it does, in fact, find the button, but nothing happens with the click() command. The button it finds includes this save command that doesn't appear to execute:
document1.getDocument(true).save();
The button works perfectly when clicked by mouse or tapped by finger, but not when 'clicked' programmatically by another button on a CC.
The currentDocument global variable can be used to access the nearest dominoDocument datasource. Alternatively, the Extension Library dialog box has an additional parameter when closing the dialog box, the id of the refresh area. Maybe you can use that to trigger a save, something like setting a requestScope variable on close, and in the refresh area having code that does a save if the requestScope variable is set and, after save, clearing the requestScope variable?

To fire file upload control on click event - xpage

Can anyone please advise how to fire file upload control in Xpage during OnClick or Onfocus event in IE? it works by default in Firefox.
Strictly speaking, when a person selects a file in the File Upload control, after it associates with the file, it is prepared for uploading (request phase data). The native control has a couple things to lack that I wish for in future releases, but basically to achieve "Upload" button functionality, which I recommend for reasons below, you should:
Create a button control which triggers a Full Refresh (returning true if the SSJS getFilename() off the fileUpload control is true); note it must be a Full Refresh!
Make sure you run it with "Process data without validation" checked (aka- disableValidators="true")
Your button should read like:
<xp:button value="Upload" id="button1">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete" disableValidators="true">
<xp:this.action><![CDATA[#{javascript:
getComponent("fileUpload1").getFilename()?true:false}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
All the users I've run into expect an "Upload" button. I'm not saying this is the best or most optimal way, but it is what people look for. My experience has taught me to cater to the users' expectations. They may be wrong to expect such, but it makes sense in the context of what we're doing here at least.
I'm sure there's a way of triggering a full refresh automatically, possibly with an onComplete event. I'm not sure whether this could be an onBlur event for the xp:fileUpload control or would be a different listener off the getComponent("fileUpload1").getFilename() value. Perhaps a more experienced XPage Dev. can answer that specifically.
Hope this helps.

Creating a response document via a button

I have two forms, Organisation and Contact. Contact is a response to Org, and each form has an XPage where the form can be filled in, saved etc. When opening edit_contact.xsp directly and creating a document (not as a response to an org), everything works fine.
On edit_org.xsp, I have a button with 2 events. The first copies some values into sessionScope so I can inherit them into the Contact. The second is a "Create Response Document" event which creates a new response with the parent ID being the current org document, and sends the user to edit_contact.xsp. Pressing the button changes XPage correctly and the field inheritance works fine, but pressing "Submit" on the Contact form doesn't save anything, and no document is created.
This exact same setup works 100% as desired in another database, I have no idea why it won't work properly here. Is there an obscure setting somewhere I am missing?
<xp:button value="Create Contact" id="button1" rendered="#{javascript:!document1.isEditable()}">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action>
<xp:actionGroup>
<xp:executeScript>
<xp:this.script>
<![CDATA[#{javascript:var doc = document1.getDocument();
sessionScope.PFirstName = doc.getFirstItem("P_Firstname").getValueString();
sessionScope.PSurname = doc.getFirstItem("P_Surname").getValueString();
sessionScope.PFamily = doc.getFirstItem("P_Family").getValueString();
sessionScope.PDOB = doc.getFirstItem("P_DOB")
sessionScope.PAGE = doc.getFirstItem("P_Age").getValueString();}]]
</xp:this.script>
</xp:executeScript>
<xp:createResponse name="/edit_contact.xsp" parentId="#{javascript:document1.getNoteID()}">
</xp:createResponse>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>`
Here is a link that shows what I am trying to do (minus the field inheritance):
http://min.us/mKSJED8tT
Currently the forms and views all work, but the document created with the "Response" form appears not to be a response document - it has no $REF field. This setup works perfectly in a different database - what is going on?
It's hard to tell what might be happening without seeing any code. Since it works for you in another database, could it be an ACL issue? Where the user you're logging in as - possibly - anonymous - doesn't have the ability to create documents?
Instead of "push" approach go for "pull" - just open response page with url parameter of parent document. In its postNewDocument event initialize field values from it.
It would be useful to get an update on two key points made by others:
Is ignoreRequestParams set on your response document datasource? If not, regardless of what you're trying to define for the second datasource, it's UNID etc are pulled from the request parameters. So both datasources are effectively the same datasource.
Is it throwing a validation error? If so, nothing will be saved.
There are two possible issues:
First the use of getFirstItem("x") is not a best practice. So:
sessionScope.PDOB = doc.getFirstItem("P_DOB")
would be storing a NotesItem in the sessionScope which will not work. It is recommended to use:
sessionScope.PDOB = doc.getItemValueString("P_DOB");
Second the use of getNoteID() might not be returning what you want (Which is the UNID of the document). Use .getDocument().getUniversalID() instead.
<xp:createResponse
name="/edit_contact.xsp"
parentId="#{javascript:document1.getDocument().getUniversalID()}">
</xp:createResponse>
-edited-
/Newbs

Resources