Your Development & Design Resource
File Upload XPage Forms via OpenNTF.org Extension Library Dialogs
12/16/2011 03:12:00 AM by Chris Toohey
The OpenNTF.org Extension Library (often referred to as ExtLib) is an absolutely must-have set of controls that can be used to quickly create some pretty amazing XPage applications. There are, however, limitations -- more due to the way things work than the technology or developers contributing to the ExtLib -- that can cause confusion and in some cases downright frustration!
I ran into one of those recently with my team, as we wanted to use the ExtLib Dialog control to surface a simple File Upload form. As you can probably guess from the name, this form stores files.
Putting the contents of an XPage inside of an ExtLib Dialog control is quite frankly a rather simple thing. What is not simple however is trying to use that Dialog'ed-form to save multi-type content back to a given NotesDocument.
Note: this is a rather long article. As such, I've created anchor links to the 11 minute YouTube video walkthru of the XPage demo application and techniques discussed here, or for those of you who prefer a more hands-on approach, you can simply jump right into the Dailog File Upload Controls -- Online XPage App Demo!
First, let's give a quick overview of the ExtLib Dialog control.
That's a rather simple ExtLib Dialog control. You define a unique ID, and place your intended content (let's say our XPage form).
hide() the Dialog control.
Here's a complete XPage that uses the Hello World! Dialog control:
The result of this is a rather small (as the Dialog sizes [by default] to the contents of the Dialog control) DHTML-style modal popup (with semi-transparent masking of the lower z-indexed background controls)... that's not really even worth showing via screencap.
'Hello World' ExtLib Dialog Control in action!
This ExtLib Dialog control will accept an entire form worth of XPage controls and pass-thru markup, allowing you to create a rather slick and certainly custom-to-the-need DHTML modal pop-up XPage form.
On submission of this XPage form -- regardless of your setting the submit button's
refreshMode property to "complete" (in other words, attempting to force a "Full Update" submission of the XPage form), the form will only write back to the target NotesDocument via the HTTP GET method.
This works flawlessly for almost every type of XPage form you could want in this context. For example, you could use this technique to create a rather simple single-value changer for a datetime, input, textarea, and other text/plain-type of content. Add that to a viewPanel for some slick on-the-fly ViewEntry update operations and you've got a solution in itself.
But if, let's say, you want to add an attachment via the core XPage fileUpload control... well, that's where you'll run into problems.
The HTTP GET method can not support multipart/form-data content types. Well, at least in the realm of out of the box ExtLib Dialog controls it can't.
If you have a fileUpload control on your XPage form, and you're surfacing that form via the ExtLib Dialog control as a cool looking file upload pop-up, any text/plain content will be written correctly back to the target NotesDocument... but the would-be-attached file won't be there!
Take that exact markup, put it in it's own XPage however (sans Dialog), and it'll work perfectly.
So I started thinking about ways that we could work around this limitation, mostly because I had fallen in love with the idea of providing this sweet-looking user experience (that quite frankly just feels natural...), and it hit me: there's no reason that I have to use the out-of-the-box, textbook implementation of the ExtLib Dialog control to get the job done. I could use an HTML IFRAME element!
Here's an 11 minute, 720p walkthru of the techniques we'll discuss for the rest of this article:
See, it's all about the IFRAME!
ExtLib Dialog IFRAME wireframe
Using the IFRAME as a portal, I could just simply surface a fully-functional XPage -- in this case, fileupload.xsp -- which could handle the HTTP POST method submissions.
I'm happy to say it worked a treat... but getting it to upload a file attachment via the fileUpload control and appearing to all be part of an ExtLib Dialog control was the easy part. The hard part was getting the various interactive functions and nailing down the whole user experience so it didn't feel choppy.
While I'd like to say that it was hard work and that it took me countless hours to get it working... that couldn't be further from the truth. It turned out to be quite easy in fact.
Home.xsp XPage Process Diagram
The Dialog control would simply contain an IFRAME (actually, it contained a rather simple Custom Control that I wrote that generated a simple HTML IFRAME element). The source of that IFRAME would be the fileupload.xsp XPage.
The cc_iframe.xsp Custom control:
The ExtLib Dialog using the cc_iframe.xsp Custom control:
.hide() if we were done adding attachments.
Doing that, as it turns out, is rather simple.
Now, there are two buttons on the fileupload.xsp XPage form.
The Save & Add More Files button:
And the Save & Close button:
The Save & Add More Files button simply processes the Full Update submission, and redirects the user to a new instance of the fileupload.xsp XPage form. Since this happens within the IFRAME, the user doesn't experience the browser redirect. In fact, it seamlessly brings up a new form so the user can continue adding attachments.
In fact, as an added bonus, every time the fileupload.xsp loads, it runs the
I do this so every time I add a new file attachment NotesDocument, the viewPanel containing the list of NotesDocuments will update to reflect the latest addition.
I use this exact approach with the hideDialog.xsp XPage (which is redirected to post submission using the Save & Close button:
onComplete argument) it 2) initiates the
.hide() of the ExtLib Dialog control.
... and that's it really. The ExtLib Dialog control combined with the HTML IFRAME which opens a fully-functional XPage that will actually process via the HTTP POST method makes for a completely solid, dependable, and (like good CGI in a movie) completely transparent user experience. The user will never know all of the hard work and russian nesting doll-like architecture that went into giving them a rather useful little feature.
Want to take the demo for a spin? I only ask that you adhere to Wheaton's Law here, since Anonymous has Editor w/ Delete rights to the online demo. Also, I've told the fileUpload control to only accept
image/*... so it simply won't submit if you try to put anything else in there.
That being said, have at it:
And when you're done taking the demo for a spin, come back here and let me know what you think via the comments section below.