Redirecting to Non-XPage
Recently I was developing a hybrid application. It had an XPage for the view (because I like the view container control with the pager controls available in XPages) and a traditional web form (because I hadn't converted it to an XPage yet). In the view control, you can click on a column to open the document either in its default XPage or in another XPage. But there was no option to open the document with its underlying form.I found a very elegant solution to this situation. First, I added an empty column to the very left (the first column in the view). This column had a value of a single space (" "). I made sure it was added to the View control on the XPage as the first column. In theory, the column could be the last column in the view and the first column in the XPage's view control, but that's not the point of this article. It needs to be a column in the view control, and also it needs to use the "show values in this column as links" property enabled, as shown in figure 1. The "Document open mode" of "edit" or "read-only" doesn't matter - it can be either.
Next, I used an answer I found on Stack Overflow and adjusted it a little. The Stack Overflow answer I found was from Knut Herrmann and it talked about applying a "show values in this column as links" to an entire table row. Here's a link to the original document. But, in short, you add a variable called "row" to your View Panel, then add an attribute to each row. This is done through row attributes added to the view panel. The JavaScript function and the "render" is what I changed slightly from the Stack Overflow answer. First, I didn't have categories or totals in my view, so I didn't need the "rendered" - it was always going to render. Second, Knut's code makes a call to open the document. Mine calls another JavaScript function. Here's my updated row attributes:
<xp:viewPanel rows="30" id="viewPanel1" var="row">
<xp:this.rowAttrs>
<xp:attr
value="openDocument('#{javascript:row.getOpenPageURL(null, true)}')"
name="onclick">
</xp:attr>
</xp:this.rowAttrs>
The JavaScript function "openDocument" is where the URL gets translated from a "XPage-type" URL to a "Traditional Domino-type" URL. This code is stored in an external client-side JavaScript file that is brought in as a resource into the XPage. Here is the function:
function openDocument(fullURL) {
var key1 = "documentId=";
var i = fullURL.indexOf(key1);
if (i == -1) return;
var docID = fullURL.substring(i+key1.length, fullURL.length);
if (docID.indexOf("&") != -1) docID = docID.substring(0, docID.indexOf("&"));
var key2 = "$$OpenDominoDocument";
i = fullURL.indexOf(key2);
if (i == -1) return;
var dbPath = fullURL.substring(0, i);
var urlToOpen = dbPath + "0" + "/" + docID + "?OpenDocument";
window.location = urlToOpen;
}
The format of the URL that comes into the function is:
/subdir/filename.nsf/$$OpenDominoDocument.xsp?documentId=<document unid>&action=openDocument
The action is based on whether "read-only" or "edit" was set in the view column property inside the view panel, but that value doesn't matter to the JavaScript. What matters to the JavaScript code is the path to the database (everything before "$$OpenDominoDocument") and the document ID (everything between "documentId=" and the "&" character).
The JavaScript code will pull out those two pieces of information. If either doesn't exist, the code simply exits without causing an error. Assuming both exist, a new URL is built in the "old-style" way of Domino development: The path to the database, then the UNID of the view (the example code uses "0" as the view, which says the default view -- you can update it to include a view alias if you want), then the UNID of the document to open, then the comamnd ("?EditDocument" or "?OpenDocument"). In this example, I wanted to open in read mode.
Now, the XPage shows the view, and when the user clicks anywhere within a row, the document is opened in read mode using the "old-style" Domino form instead of any XPage. This provided me with some additional time to develop the form in XPages (it's a pretty complex form that makes use of Web Query Open agents, lots of in-line computations, and so on). One thing to point out is that you might want to use CSS on your view panel to change the user's cursor to a pointer when they are on a row so they visually can see that the row can be clicked. I also added CSS to highlight the row entirely, which helps visually. But the point of this article was the JavaScript to run when the user clicked on the row.