I have a repeat-control which generates me a list of links to documents in a different database.
Special on this task is that the XPage runs in the notes internal browther (NOT XPniC) and open the documents as real notes documents in the notes client (NOT Xpages). so far every thing works fine.
Now I want too check if the document exists before I open the document.
My solution is an xAgent which check if the document exists and redirect to the NotesURL but I get the following error:
Error source
Page Name:/xaOpenDocument.xsp
Exception
Error while executing JavaScript action expression
Script interpreter error, line=25, col=43: Error calling method 'redirect(java.lang.String)' on java class 'com.ibm.xsp.domino.context.DominoExternalContext'
notes://SERVER01#SRV#DE#OU#MyCompany AG/__C1257B6B002A0472.nsf/0/C1257B6B002A0472C12574CD0024E6B9
The link to the xAgent looks like this:
http://SERVER02/dev/release_4/test_xui.nsf/xaOpenDocument.xsp?dbServer=SERVER01%2FSRV%2FDE%2FOU%2FMyCompany+AG&dbPath=dev%5C%5Crelease_4%5C%5Ctest_adr&docUNID=C1257B6B002A0472C12574CD0024E6B9
The xAgent code looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" rendered="false">
<xp:this.afterPageLoad><![CDATA[#{javascript:var server:string = context.getUrlParameter("dbServer");
var db:string = context.getUrlParameter("dbPath");
var unid:string = context.getUrlParameter("docUNID");
var url:string = "";
var targetDB:NotesDatabase = session.getDatabase(server,db);
var doc:NotesDocument = targetDB.getDocumentByUNID(unid);
if(doc == null){
requestScope.put("targetDocUNID",unid);
println("xaOpendocument targetDocUNID: " + unid);
requestScope.put("dbServer",server);
println("xaOpendocument dbServer: " + server);
requestScope.put("dbPath",db);
println("xaOpendocument dbPath: " + db);
requestScope.put("targetError","Dokument konnte nicht geƶffnet werde. \n Document wurde verschoben oder entfernt.");
println("xaOpendocument URL: xpErrorMessage.xsp");
context.redirectToPage("xpErrorMessage.xsp");
}else{
url = sessionUser.getDocumentURL(targetDB,unid);
println("xaOpendocument: Dokument wurde gefunden... Umleiten!");
println("xaOpendocument URL: " + url);
facesContext.getExternalContext().redirect(url);
}}]]></xp:this.afterPageLoad>
</xp:view>
The Serverconsole shows me the following error lines:
30.07.2013 11:17:47 HTTP JVM: xaOpendocument: Dokument wurde gefunden... Umleiten!
30.07.2013 11:17:47 HTTP JVM: xaOpendocument URL: notes://SERVER02#SRV#DE#OU#MyCompany AG/__C1257B6B002A0472.nsf/0/C1257B6B002A0472C12574CD0024E6B9
30.07.2013 11:17:47 HTTP JVM: com.ibm.xsp.webapp.FacesServlet$ExtendedServletException: com.ibm.xsp.exception.EvaluationExceptionEx: Error while executing JavaScript action expression
30.07.2013 11:17:47 HTTP JVM: CLFAD0134E: Exception processing XPage request. For more detailed information, please consult error-log-0.xml located in F:/Lotus/data/domino/workspace/logs
I hope for some useful help - I wasted already to much time on this problem. I thought it should be simple. :/
Your problem is that you are trying to do a server side redirect.
instead of
facesContext.getExternalContext().redirect(url);
try this
view.postscript('window.location.href="+url+"')
To make the redirect client side instead
The problem is that the XPages Engine does not know the notes:// url format. Internally the given URL parameter will be converted with java.net.URL, and this throws an error.
Maybe you can send your own HTTP headers instead for the redirection to the notes:// URL.
EDIT:
This should do the trick:
}else{
url = sessionUser.getDocumentURL(targetDB,unid);
println("xaOpendocument: Dokument wurde gefunden... Umleiten!");
println("xaOpendocument URL: " + url);
var resp:com.ibm.xsp.webapp.XspHttpServletResponse = facesContext.getExternalContext().getResponse();
resp.setStatus( 302 );
resp.addHeader("Location", url );
facesContext.responseComplete();
}
I figured it out.
The main problem was to call CSJS in backend functions for the redirect., becourse ssjs facesContext.GetExternalContext().redirect(url) could not handle my notes url (notes://...).
One hint by Frederic Norling was to use the view.postscript('window.location.href="+url+"'), but this function is only supported with Notes/Domino 8.5.3+ (sadly we use 8.5.2).
The enlightenment comes with my discovery of the EventHandler- Event "onComplet()".
Now I create a Link component with a onClick()- Event:
<xp:link escape="true" id="link1" tabindex="-1" style="font-weight:bold">
<xp:this.text>MyLink</xp:this.text>
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial" refreshId="refreshCheckDoc">
<xp:this.action>
<![CDATA[#{javascript:<some code for checking my URL Target and write the URL in a requestScope variable when the target exist else I write a propper ErrorMessage in a requestScope Varaible>]]></xp:this.action>
On my XPage I have a panel with the id "refreshcheckDoc" an on this Panel I have two hidden fields. The first Field get his value from the requestScope.url the other get the requestScope.ErrorMessage. On the onClick()- Event I attached the onComplet()- Event.
In the onComplet()- Event I check the content of the two fields. Is the url empty AND the errorMessage I do nothing. If I have the url I call window.location.redirect(url), if I have the ErrorMessage I use the alert() function to inform the user about the error.
Thanks for all Your help. I hope this short description is helpful for others, too.
Related
I want to send emails from an Xpage application. Want to include some type of header graphic or HTML styling, and it must include a doc link.
I started using Ulrich Krause's modification of Tony McGuckin's excellent SSJS here
However, I have two issues that I cannot resolve - adding the doc link an and also a graphic.
var doc:NotesDocument = currentDocument.getDocument();
var tmp:String ="A New Location Has Been Created: " + document1.getDocument().getItemValueString("businessUnitName") + ".\n\n" + "Please click this doc link and add any additional approvers ==> ";
emailBean.setSendTo("name#domain.com");
emailBean.setSubject("Lcoations");
emailBean.setSenderEmail("name#domain.com");
emailBean.setSenderName("Locations");
emailBean.setFieldName("Body");
//emailBean.setDocument(document1);
emailBean.addHTML("<table><tr><th>Month</th><th>Savings</th></tr><tr><td>January</td><td>$100</td></tr></table>")
emailBean.addHTML(tmp);
emailBean.setBannerHTML("<table><tr><th>Month</th><th>Savings</th></tr><tr><td>January</td><td>$100</td></tr></table>");
emailBean.setFooterHTML("<p>Kind regards,<br/>Samantha<br/>0012 3456 789</p>");
emailBean.send();
I have commented out the setDocument code as it doesn't work and isn't necessary.
I have an image resource in the db called locations.pgn that I want to include - or I can put it on the web at a url I control.
How do I pass in a doc link? I have computed it, but I just don't now how to add it.
The other method I have tried is a more roll my own.
I have this in a button on the Xpage form:
var doc:NotesDocument = currentDocument.getDocument();
var nteUrl:String = doc.getNotesURL();
var sndTo:String ="name.domain.com";
var sndFrm:String ="ame.domain.com";
var sbj:String ="A New Location Has Been Created: blah blah blah");
var body:String =""A New Location Has Been Created: blah blah blah");
sendEmail(sndTo,sndFrm,sbj,body,doc);
And then my function:
function sendEmail(sndTo,sndFrm,subject,body,trgDoc) {
var doc:NotesDocument = database.createDocument();
doc.replaceItemValue("Form","Memo");
doc.replaceItemValue("Subject",subject);
doc.replaceItemValue("Principal",sndFrm);
doc.replaceItemValue("From",sndFrm);
doc.replaceItemValue("SendTo",sndTo);
doc.replaceItemValue("DisplaySent",sndTo);
doc.replaceItemValue("SMTPOriginator",sndTo);
var memo:NotesRichTextItem = doc.createRichTextItem("Body")
var urlgif="/locations.png";
memo.embedObject(NotesEmbeddedObject.EMBED_OBJECT, "",urlgif,null);
memo.appendText(body);
memo.appendDocLink(trgDoc);
doc.send();
return ;
}
This attaches the file as an attachment, not as a picture. Can't find a method to do that.
I am agnostic about which method I use, I just want to get one nailed down and tightened up so I can use it throughout my applications.
Any help would be greatly appreciated.
You create the email based on HTML with emailBean.addHTML(... your html ...).
Use the syntax
link text
to add links and
<img src="url" ...>
to add images.
Instead of an URL you can code the picture in base64 and include it completely in your html like this
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZ
AQAAAADskrjOAAAAfElEQVR42mNgrDrAwFCbHs/A4Gp8EUgIBAKJSUCiVuY+A
wNjqAMDw//T/xsYDK9nMDB4/zAGSkimMTAIbz/DwHDitRwDg1agNQPD0YTyBoZ
L/ncbGHg3swN1WBcD9f4Lb2CoLS8AmufB3sDgehWo2LXRDSjmtRkoG5TCAACQ
1SM9QzyOtAAAAABJRU5ErkJggg==">
I have a contact form where I use the email bean found on OpenNTF snippets to send the email out. That part works great.
Once the email is sent, I am showing a dialogbox with a little message to let the user know that the message was sent. What I would like to do, and can't figure out, is to redirect the user to the homepage once he hits the close button on the dialog.
Here's the code in the button:
<xp:button id="button1" value="Send">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:try{
//var sendTo = document1.getItemValueString("SendTo");
var sendTo = AppConfig.getAppEmailAddress();
//var subject = document1.getItemValueString("Subject");
var subject = "Belair Docum: " + document1.getItemValueString("category") + " - " + document1.getItemValueString("Subject");
//var senderEmail = "noreply#belairdirect.com";
var senderName = userBean.abbreviatedName;
emailBean.setSendTo(sendTo);
emailBean.setSubject(subject);
emailBean.setSenderEmail(senderName);
emailBean.setSenderName(senderName);
emailBean.setDocument(document1);
emailBean.setFieldName("Body");
emailBean.setBannerHTML("<p>Email sent from belair Docum 2.0</p><hr>");
//emailBean.setFooterHTML("<hr><p>Email sent from belair Docum 2.0</p>");
emailBean.send();
var d = getComponent('dialog1');
d.show();
}catch(e){
print(e.getMessage());
}}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
I tried to put this in the Dialog's Dojo onClose event, but it doesn't work:
window.location.pathname = "/home.xsp"
Can it be a refresh issue, or I am not using the proper event, or I need to use different code?
Thanks :D
Ben,
This would be a good case to use view.postScript() Add this to the end of your SSJS code, and put clientside javascript in there to redirect to wherever you want. It will only run at the completion of your serverside code.
Steve, I ended up with a very simple solution...
In the onHide event of the dialog (not the onClose), I have put this little client side snippet:
path = location.pathname.split('.nsf')[0] + '.nsf/';
window.location.href = path + "/home.xsp";
And that works. The button still requires a partial refresh to trigger the dialog, and I have put it on the dialog itself (dialog1).
I'll give your solution a try, though. :D
I have a computed field on an xpage the result of which is HTML. In that HTML I want to compute a link that will trigger some server side js function followed by a partial refresh.
My current code looks like this:
Click Here
This will work if my js function is a client-side function but I want to use this function to set the value of a field on the document so I need SSJS.
Static links that are created from the controls pallet in an xpage allow the link to call SSJS with partial refreshes. How can I do this with a computed HTML link?
Another option could be creating your own event handler and executing that via client side JavaScript code described in this article. So suppose you create an event handler something like this:
<xp:eventHandler event="name" id="eventhandler1a">
<xp:this.action>
<xp:saveDocument />
</xp:this.action>
</xp:eventHandler>
You can then create a function to call this event handler via JavaScript code:
XSP.executeOnServer = function () {
// the event handler id to be executed is the first argument, and is required
if (!arguments[0])
return false;
var functionName = arguments[0];
// OPTIONAL - The Client Side ID that is partially refreshed after executing the event handler
var refreshId = (arguments[1]) ? arguments[1] : "#none";
var form = (arguments[1]) ? this.findForm(arguments[1]) : dojo.query('form')[0];
// catch all in case dojo element has moved object outside of form...
if (!form)
form = dojo.query('form')[0];
// OPTIONAL - Options object containing onStart, onComplete and onError functions for the call to the
// handler and subsequent partial refresh
var options = (arguments[2]) ? arguments[2] : {};
// OPTIONAL - Value to submit in $$xspsubmitvalue. can be retrieved using context.getSubmittedValue()
var submitValue = (arguments[3]) ? arguments[3] : '';
// Set the ID in $$xspsubmitid of the event handler to execute
dojo.query('[name="$$xspsubmitid"]')[0].value = functionName;
dojo.query('[name="$$xspsubmitvalue"]')[0].value = submitValue;
this._partialRefresh("post", form, refreshId, options);
}
You can then call the event handler via this client side JavaScript code:
XSP.executeOnServer('#{id:eventhandler1a}', '#{id:panel1}')
Here panel1 refers to control which would be partially refreshed.
You can stick with your code if you use the XSP Object in the myFunction() client side function. This allows you to call a partial refresh. The other option is to call a Extlib JSON control and have your logic there. Depends a little on your coding style
The link control is not static. You can compute whatever you want, for example:
<xp:link escape="true" id="lnk">
<xp:this.value><![CDATA[#{javascript:"#"}]]></xp:this.value>
<xp:this.text><![CDATA[#{javascript:"Label here"}]]></xp:this.text>
</xp:link>
I am trying to post an update i.e. a status message to IBM Connections using the extlib.
I have used the extlib with connectionsLTPA endpoint which works really well for getting the communities list. However I wish to add functionality to update the users status.
So far I have tried using
<xp:this.data>
<xe:connectionsData var="connectionsData1"
endpoint="connections" serviceUrl="/profiles/atom/mv/theboard/entry/status.do?email=#{userBean.email}">
</xe:connectionsData>
</xp:this.data>
and then in the event handler
var sb = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<author><name>#{userBean.displayName}</name></author>" +
"<entry xmlns=\"http://www.w3.org/2005/Atom\">" +
"<content type=\"html\">" +input + "</content>" +
"<category scheme=\"http://www.ibm.com/xmlns/prod/sn/type\" term=\"status\" />"+
"</entry>\r\n";
var output = #{connectionsData1}.post(null, sb, "xml");
however this throws an error trying to call post on the binded data point.
Anybody able to point me in the right direction?
Thanks
I have found that implementing the sbt by doing the follwing:
<xp:button id="button2">
<xp:this.value>Update my status</xp:this.value>
<xp:eventHandler event="onclick" submit="true"
refreshMode="partial">
<xp:this.action><![CDATA[#{javascript:try {
var svc = new sbt.ConnectionsService("/profiles/atom/mv/theboard/entry/status.do?email=" +userBean.email);
var sb = new java.lang.StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
sb.append("<entry xmlns=\"http://www.w3.org/2005/Atom\">");
sb.append("<category scheme=\"http://www.ibm.com/xmlns/prod/sn/type\" term=\"entry\"/>");
sb.append("<category scheme=\"http://www.ibm.com/xmlns/prod/sn/message-type\" term=\"status\"></category>");
sb.append("<content type=\"text\">");
sb.append(getComponent("inputText1").getValue());
sb.append("</content>");
sb.append("</entry>");
var msg = svc.put(null, sb.toString(),"xml");
var msg = "updated users profile status";
#WarningMessage(msg)
} catch(e) {}
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
The reason it wasn't working correctly is that the atom feed needed to be declared as an entry. This article in the connections doc for 2.5 http://publib.boulder.ibm.com/infocenter/ltscnnct/v2r0/index.jsp?topic=/com.ibm.connections.25.help/r_api_prof_update_photo.html explains the required parts of the xml atom document.
<t:panelTab label="Detailed View" styleClass="tabFont" rendered="true" id="DetailedView">
<t:dataTable value="#{MyFinanceBB.amendDataList}" id="DetailedViewGrid" forceId="true"
var="myVo" rowIndexVar="gridExpRowNo"......>
...............
<t:inputText value="#{myVo.myval}" styleClass="BodyFont" forceId="true" id="myId2"
onchange="getTotalMyValAjax('myId2[#{gridExpRowNo}]',#{gridExpRowNo});">
/----------------------------------------------------------------/
function getMyAmountTotalGrid(myidVar,count){
var myAmt=document.getElementById(myidVar).value;
var id = 'myForm\\:targetView';
$j.ajax({
async:"false",
cache:"false",
type: "POST",
url:"/myProj/myController",
data:{myAmt:myAmt,count:count},
error:function(){
alert('Error Occurred.Please try later');
},
success:function(output){
alert('SUCCESS');
$j('#'+id).load("/pagesmyProj/Home/dingDongHome.jsf");
alert('after reloading grid');
}
});
}
when i execute the code alert message SUCCESS is getting printed and all the server side variables are getting updated.(I came to know this by sysouts). But nothing is really getting changed in the webpage. The alert message "after relaoding grid" is also getting printed. But the grid is not getting reloaded. The server side changes are not getting reflected in the browser.
For start you should add \\ to your id
instead of var id = 'myForm:targetView';
write var id = 'myForm\\:targetView'; otherwise jquery selector by id wont work (you need to escape the :)
You are referencing
$j('#'+id)...
just remove the "j", ex. $('#'+id)...
After a long struggle,I got the error.The url given to the jquery load function is not proper and it should be changed.