Domino 8.5 - xPages
PermaLink XPages - Example on how to generate dynamic controls for your fields at runtime07/20/2009 12:01 PM
Domino 8.5 - XPages
In my XPages Survey tool example that I demoed at Lotusphere, I showed how to dynamically generate fields at runtime for a document collection. The tool allows an administrator to create survey questions and select the control type and selection values.  Then the tool generates the fields for the questions when the user opens a survey.  The XPage utilizes a repeat control and panel control to accomplish this.  

For today's example I pulled out the specific code that generates the fields,  i.e. checkbox, list, radio button, edit box, etc.,  and simplified it so that it is clearer how this technique works....and just how easy it is to implement.  In the full survey tool example, this feature and technique easily gets lost.

You can download the sample database here.

The real key to this technique is the separation between presentation and data in XPages as compared with traditional Domino development.  With XPages, you can have multiple controls bound to the same Lotus Notes fields.  As long as only one of these controls is rendered at runtime, there is no issue with data integrity.

Below is a screen shot of the example generating a radio button group control :
Image:John's Blog - XPages - Example on how to generate dynamic controls for your fields at runtime


Here's how it is built:

On the DynamicFieldDemo XPage, the fields in the Field Attributes section control how the control is generated.  There is one control in the Field Preview section for each possible control type.  The Required field sets the validation required property on each control to true or false.  The Generate Field button reloads the page.  This is only required for this example because we need to regenerate the controls, which is not something that would be changing for your users.

The XPage layout looks like this:
Image:John's Blog - XPages - Example on how to generate dynamic controls for your fields at runtime


The visibility formula for the "Combo Box" control returns true if the user selected "DropDown" for the Control Type.  In this example I pick the value up from a session variable:
Image:John's Blog - XPages - Example on how to generate dynamic controls for your fields at runtime


The data Binding is set the same for all the controls.  In this example I am not using a Notes form as a datasource in order to keep it simple and instead just using session variables:
Image:John's Blog - XPages - Example on how to generate dynamic controls for your fields at runtime


The Validation is set, in this case for the combo box, from the All Properties->basics->required property:
Image:John's Blog - XPages - Example on how to generate dynamic controls for your fields at runtime

The possible selection values are set by exploding out the choices using a "," as the delimiter:
Image:John's Blog - XPages - Example on how to generate dynamic controls for your fields at runtime

Lastly, the Display Error control will display an error if the field is required and you pushed the Test Validation button.  The really cool thing here is that I have only one Display Error control which I compute what control it should report errors for.  This is accomplished by computing the "Show error messages for" property.  Since the control names I used match the selection names it is easy to compute which control is being displayed:
Image:John's Blog - XPages - Example on how to generate dynamic controls for your fields at runtime

As you can see, this opens up many possibilities.  I'm sure it won't be long before you discover other uses for this technique.

-John
Technorati:
(0)

PermaLink XPages sample application - download the Survey Tool demoed at Lotusphere 09 session AD20701/28/2009 07:55 AM
Domino 8.5 - XPages
In my Lotusphere session AD207, I presented an XPages built Survey Tool application.  Here was the abstract for the session:

Building an "XPages-Powered" IBM Lotus Domino Application
An unlimited number of editable documents on the same page? Generating the type of controls for fields on page load? Dynamic applications have always been a challenge for Lotus Domino development. Not anymore! In this session, you'll learn how to utilize the power of XPages to build a survey tool that can have an unlimited number of questions. We’ll show you how to dynamically allow for the selection of controls on the page load, such as checkboxes, radio buttons, and combo boxes, etc. Go under the hood and see how we use multiple data sources per page and some powerful XPage controls to build this application with a minimum amount of coding.

The goals that I set out to accomplish in this session were:
  • To select an application that could not easily be built with the standard Domino Designer..... demonstrating the power of XPages.
  • Secondly my goal was to utilize XPage controls to build a complex application with a minimum amount of code or workarounds.  
    - Thinking “Inside the Box”....

Thinking "Inside the Box" ???  Yes, you are right, I am the first person on the planet to coin that phrase...  It was a little tongue-in-cheek humor but the point is, when was the last time you used only the tools provided for you in the domino designer to build a web application?  Probably 1998 when we all built the view with the left hand navigator.  So I wanted to show how you can build a complex application with just the tools provided in the box and with very minimal code.

An underlying key difference between standard Domino development and XPages is the separation between the presentation and the data store. This change allows a developer to build applications they could not easily build previously, and also approach application design from a different angle.  By taking advantage of this change and utilizing the built in XPage controls that exploit this separation, you can build sophisticated applications that were extremely difficult in the past.

The reason I chose a Survey tool was that a Survey Tool provides many challenges for Domino Designer:
  • It must allow an administrator to create an unlimited number of questions
  • Allow the Admin to change the order of the questions
  • Select the type of input control to display: check box, radio buttons, text box, drop down list etc.,. and render them dynamically
  • Provide dynamic validation
  • Provide dynamic navigation: one question per page, all per page
  • Report on the data

You can download my presentation, which covers the design details, here: Lotusphere 2009 presentation - AD207

You can download the SurveyTool.nsf application here (requires registration): Lotusphere 2009 sample application - SurveyTool.nsf (* see notes below)

Here's a couple of screen shots:

- Administering questions for a survey.  Note that multiple questions can actually be edited at the same time because they are independent docs:
Image:John's Blog - XPages sample application - download the Survey Tool demoed at Lotusphere 09 session AD207

- editing questions by clicking on the individual edit links:
Image:John's Blog - XPages sample application - download the Survey Tool demoed at Lotusphere 09 session AD207

- Taking a survey showing all questions on a single page:
Image:John's Blog - XPages sample application - download the Survey Tool demoed at Lotusphere 09 session AD207

- The same survey except configured to show only one question per page:
Image:John's Blog - XPages sample application - download the Survey Tool demoed at Lotusphere 09 session AD207

- Reporting on the survey by using the dojo toolbox provided with Domino 8.5:
Image:John's Blog - XPages sample application - download the Survey Tool demoed at Lotusphere 09 session AD207

This application is not 100% complete, for example access control needs to be worked out, but it's a great example app to learn some advanced XPage techniques from.  

I hope you enjoy it as much as I did presenting it....

John

* If you are installing the application on a server, remember to sign the database with your id.  Also make sure that your server document has the XPages security set properly.  Here's a link for details on setting the security: http://www-10.lotus.com/ldd/nd85forum.nsf/5f27803bba85d8e285256bf10054620d/d9851c77bf81402d852574b8005e236d?OpenDocument

** There is a bug identified with the tabbed panel control.  IBM has opened up an SPR. Here is the scenario: If you enter some data on tab 1, then go to another tab and save, the data on the first tab is lost.  If you enter data on tab 1, go to another tab and then go back to tab 1 at least 1 time during your session...the data will be saved.  

Technorati:
(20)

PermaLink My XPage samples and beta 2 - some bug workarounds09/14/2008 08:06 AM
Domino 8.5 - XPages
I received a number of emails from folks who were having issues with some samples on my site and DDE 8.5 beta 2.  I worked with the IBM developers this past week on solving the issues and finding workarounds.  Thanks to Phil Riand and Paul Hannan for working with me on these issues, I now have the below solutions.

There were 2 issues:

Getting a handle on the backend document that represents the current document for the page.  
- when submitting a document, in order to gain full access to the NotesDocument class representing the current document you need to use "doc=document.getDocument();" method.  For example, you would use this method to get a copy of the document when creating a response document for the current document.  With beta 2 the document was discarded after the save occurred and therefore calling this method produced an error.
- The workaround: use this to get a handle on the NotesDocument for the current document "doc=db.getDocumentByID(document.getNoteID());"

Generating dynamic controls for a document collection and binding each document to a panel.
- What was happening was the Save Data Sources simple action was failing.  This is a great feature in that it will save all bound documents that are on the page, instead of having individual save buttons.  You can also call this method in server side script by calling the Global function  "save();".
- The solution is to have the panel document binding computed on Page Load instead of Dynamically

Image:John's Blog - My XPage samples and beta 2 - some bug workarounds

If you click on the Source tab for your XPage, you can change this manually by changing the "#" to a "$" for your script bindings to the document IDs:

Image:John's Blog - My XPage samples and beta 2 - some bug workarounds

I was told that both of these issues are fixed for the GA build, so my previous examples should work without any changes when the product goes gold.

John
Technorati:
(4)

PermaLink Yellow Day tip: how to use Notes computeWithForm with an XPage08/11/2008
Domino 8.5 - XPages
Image:John's Blog - Yellow Day tip: how to use Notes computeWithForm with an XPage

I'm celebrating Yellow Day today here at GroupwareInc.  In honor of the celebration I have an XPages tip to share with you.

How to use Notes computeWithForm with an XPage
Here's how you can use your Lotus Notes default field formulas when opening up an XPage, or when saving an XPage, or both.

- Select your XPage Properties tab and click on the All Properties tab.  
- Navigate to data and expand data->dominoDocument[0].
- Select when to execute the computeWithForm form logic.  Your choices are: onload, onsave, or both

On the backend, this actually executes the document.computeWithForm() method.

Here is a screen shot:

Image:John's Blog - Yellow Day tip: how to use Notes computeWithForm with an XPage

Have a happy Yellow Day!

John
Technorati:
(1)

PermaLink XPages: Techniques for using Client-Side Javascript with Server-Side Javascript07/16/2008 04:55 AM
Domino 8.5 - XPages
XPages provides techniques that you can utilize between client-side and server-side Javascript.  I have a couple of examples below that show how you can stop server-side events from firing from a client script and also how you can retrieve values for use in client-side script using inline server-side script in your client js.

Events
Each event for a component can have both client-side and server-side Javascript.  When the event is fired the client-side script is executed first.  You can prevent/allow the server-side script from being executed by returning true or false from your client-side script.

For example, on a "Save" button you want to prompt the user and ask them if they are sure they want to save the document.  You can provide a client-side confirm popup on the onclick event.  If the user presses "OK" you would return "true" and the server-side script would then proceed to be executed.  If the user clicks "Cancel" you would return "false" and the server-side script would be prevented from being executed.

Here's a screen shot of the onclick event showing that there is a server-side simple action to save the document:

Image:John's Blog - XPages: Techniques for using Client-Side Javascript with Server-Side Javascript


Here's a screen shot of the same onclick event, this time I clicked on the "Client" tab:

Image:John's Blog - XPages: Techniques for using Client-Side Javascript with Server-Side Javascript


Here's the result when the button is clicked in the browser:

Image:John's Blog - XPages: Techniques for using Client-Side Javascript with Server-Side Javascript


Processing server-side script in client-side script
You can process server-side script using inline commands in your client-side code.  This is a similar technique as using computed text in Domino within a page that contains Javascript.  As with Domino, the server-side code is evaluated when the page is loaded.

For example, you want to retrieve values from a Notes document and use that value in client-side script.  On the client-side onclick event for the button, you can place the following simple EL expression:
Image:John's Blog - XPages: Techniques for using Client-Side Javascript with Server-Side Javascript


Here's the result if you click the button in your browser:

Image:John's Blog - XPages: Techniques for using Client-Side Javascript with Server-Side Javascript

or you can use server-side Javascript to perform the same task as the EL expression:

Image:John's Blog - XPages: Techniques for using Client-Side Javascript with Server-Side Javascript


or let's say you have a session variable from another page:

Image:John's Blog - XPages: Techniques for using Client-Side Javascript with Server-Side Javascript

or...here I am getting the database name using an @Function::

Image:John's Blog - XPages: Techniques for using Client-Side Javascript with Server-Side Javascript

Image:John's Blog - XPages: Techniques for using Client-Side Javascript with Server-Side Javascript

As you can see, you can pretty much execute any server-side Javascript to return the values you want.  This includes server-side js functions from script libraries if they are set as resources for the page.

Additional resources:
Last year there was an article written by Jason English and my good friend Sal Mazzotta for Lotus Component Designer titled Client-side JavaScript techniques and demos.  Though all of it does not apply to XPages, you can find techniques similar to the above as well as additional techniques that might be useful.

John
Technorati:
(11)

PermaLink XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 107/07/2008
Domino 8.5 - XPages
* please note: This example has been updated to work with 8.5 Gold.

I have been reading many of the discussions this week concerning JavaScript as the language for XPages.  I can understand many of the concerns and questions as to why JavaScript?  So, I decided to demonstrate one of the advantages of using JavaScript as the server side language for XPages.  In the below example I demonstrate how easy it is, and how powerful it is, to call Java methods directly from JavaScript.  You can download the example Domino database by clicking here: XPagesJSToJava.nsf

JavaScript can call Java methods directly and pass variables to and from those methods.  There are some "type" differences between Java and JavaScript that you need to be aware of.  I believe the charts on this site outline the variable conversions well: Javascript to Java Conversions.  In the below example I pass string values directly from JavaScript to and from Java, which is straightforward and without any conversion issues.

Since Domino 8.5 is Eclipse based, you can switch to the Java perspective and add Java code to your project. The nsf database is the project.  (If you haven't done this yet, it is interesting to switch perspectives and look around at the structure and the code.)  By switching to the Java perspective, you open up your code to the importing or referencing of Java libraries, or the creation of your own classes.  

What makes calling Java methods directly so powerful in XPages is that nearly every property in an XPage can be computed, and wherever these's a computation you can use JavaScript for the value or formula.  For example,  this will allow you to call Java for: populating data sources, labels, view column labels, view data columns, computed text, visibility formulas, any place you see a diamond (which is everywhere)...as well as all server side events.  So, wherever you can call JavaScript you can also basically call Java methods!

Example Overview
In this example I am calling a Java method that will return data from a DB2 database. I pass in the query and I receive a concatenated string as the result.  If you want to follow the example, and you do not have DB2, you can download DB2 9C for free from here: DB2 Expess-c 9.5.  After the install you will see an option to create the Sample database, select this and you will have pre-populated tables to work with.

**Just a note that this is just for demo purposes and performance was not a key consideration.  Hopefully access to relational databases will be native in a future release.

This is a screen shot of the Employee XPage.  The Combo Box Control's values are populated with a JavaScript call to "getDeptNumbers()".  This function calls the Java method "javaMethods.SQLQuery.executeQuery()" which is the Packagename.Class.Method() of the method we want to call.  The last line of the JavaScript function I use an "@Explode" in order to convert the string to an Array for the Combo Box values.  There's very minimum amount of code in this example so it will be easy to implement.
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 1
** update 7/9/08 - I changed the location of the SQLQuery.java file in Part 2 of this article and it is different than in the Eclipse screen shot

Here is a screen shot of the Employee View where I perform a dynamic SQL lookup on the last column.  Nathan Freeman posted an example of performing a @DbLookup on a view column.  It's a great example, and a great change in how we as Domino developers can utilize views in XPages.  View columns can contain any JavaScript formula in XPages, so they can be dynamic.

As the view is rendering it is dynamically performing SQL lookups for the Department Name by passing the ColumnValue "Depart. No." to the JavaScript function "getDepartment(deptNo)".  This function makes a call to executeQuery passing in the "where" clause so we only retrieve the single Department Name for each Dept. No. in a row.   Now....I Know what you are thinking....performance obviously would be a consideration in really using this technique....but it's really cool example nonetheless!
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 1

How to build it

Click here to continue with Part 2: How to build it.....

Technorati:
(14)

PermaLink XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 207/07/2008
Domino 8.5 - XPages
This is Part 2 of this example.  Click here to read Part 1.

How to Build It
I'll go over the steps in detail here.  The steps are actually very few.  I found that the SQL.jar file is already included in the project, so you do not need to import any jar files into the Eclipse project.  You can download the example Domino database by clicking here: XPagesJSToJava.nsf

Database Setup
Install DB2 if you haven't already.  The sample table that we will be using is Department. This is a screen shot of the table and the data.:
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2
**note: I used the Administrator id when generating the sample tables so the schema is Administrator.  This might be different for you.  You will need to use the correct schema name in your query.

You will need to copy the following db2 jar files from the DB2 installation directory "SQLLIB\java\db2jcc.jar" and "SQLLIB\java\dbjcc_license_cu.jar" to your "Domino\xsp\shared\lib" directory.  There might be another way to reference the jar files by editing the Notes.ini, but this works too.


Lotus Notes Designer
Create your new Lotus Notes db XPagesJSToJava.nsf in DDE.

Now switch to the Java perspective by selecting: Window->Open Perspective->Other.  You will be presented with the below list of choices.  Select Java and click OK.
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2


Expand your project on the Left hand Project navigator.  Select the WebContent/WEB-INF Folder:
- right click and select New->Folder.  Name the folder source, click Finish.
- right click on the source folder and select New->Package.  Name the Package javaMethods click Finish.
- right click on the javaMethods package and select New->File.  Enter SQLQuery.java for the name.  Click Finish.  

Here's a screen shot of how it should look:
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2

Now double click on the SQLQuery.java and paste in the following code:
package javaMethods;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class SQLQuery{
        public static String executeQuery(String connDB,
                        String connUserName, String connPwd, String query){
                String theResult="";
                ResultSet resultSet=null;
                try {
                        // load the DB2 Driver
                        Class.forName("com.ibm.db2.jcc.DB2Driver");
                       
                        // establish a connection to DB2
                        Connection db2Conn =
                        DriverManager.getConnection(connDB,connUserName,connPwd);
                                               
                        Statement st = db2Conn.createStatement();
                       
                        // execute the query
                        resultSet = st.executeQuery(query);
                        while (resultSet.next()) {
                                //theResult will be the 1st column separated using ";"
                                theResult=theResult+resultSet.getString(1)+";";
                        }
                }        
                catch(Exception e){
                        System.out.println(e);
                }
                return theResult;
        }
}


We need to add the source folder to the java build path:
- select the project and then select Project->Properties from the menu (or right click)
- select the Java Build Path and click on Add Folder button.  Select the new source folder.  Click OK.
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2

Your screen should look like this:
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2


Save this and switch back to the Domino Designer perspective by selecting: Window->Open Perspective->Other.  Select Domino Designer.

We will now create the server side JavaScript library for our 2 functions.  Expand Code and then select Script Libraries and click on New Server JavaScript Library.  Enter SQLFunctions for the name. Paste in the following code.  You need to change the userName and pwd variable according to your DB2 installation.  Most likely the connString will be ok if this is on your local machine.
var connString="jdbc:db2://localhost:50000/sample";
var userName="db2admin";
var pwd="password";

function getDeptNumbers(){
        var query="SELECT DEPTNO FROM ADMINISTRATOR.DEPARTMENT";
        depts=javaMethods.SQLQuery.executeQuery(connString,userName,pwd,query);
        return @Explode(depts,";");
}

function getDepartment(deptNo){
        print("dept="+deptNo);
        var query="SELECT DEPTNAME FROM ADMINISTRATOR.DEPARTMENT WHERE DEPTNO='"+deptNo+"'";
        dept=javaMethods.SQLQuery.executeQuery(connString,userName,pwd,query);
        return dept;
}



Create the Employee form.  Here is what the form fields look like:
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2

Create the Employee XPage.  If you need a refresher in creating the XPage fields, look at one of my earlier examples posted on this site.

Add a Combo Box control bound to the DepartNo field.  Click on the Values tab and click on Add Formula Item. For the formula add the JavaScript function getDeptNumbers().  Here's a screen shot:
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2


I added additional functionality that will look up the DepartmentName for any selected DepartNo.  Drag a new Button to the table. Change the label to Lookup.  On the Event tab for the button, select Script Editor and enter the below remark:
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2
Even though the remark does nothing, it causes the page to make a round trip to the server and will compute any computed text.  Another option might have been to add that code to the onChange() event of the Combo Box. (probably a better choice in retrospect)

Add a Computed Field control to the table.  Enter the following formula that will look up the Department Name by calling the getDepartment() function:
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2


Next we will create a view for the EmployeesView XPage.  Here's the layout:
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2


Create a new XPage named EmployeesView and drag a View Control to the page.  
- Make the first column a link.
- Select the View and on the Data tab, select Employee for the default XPage to open.
- Select All Properties and expand data.  Enter "detailrow" as the var.  This will allow us to reference the column values so we can perform the lookup..
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2


Next:
- append a new column in the view by right clicking on the Depart No. column and select Append Column.  
- click on the title for the new column and change the label to Department
- click on the column itself so we can enter a formula
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2


Click on the All Properties tab for the new column.
- expand data
- click on the value property
- click on the diamond and select Computed Value
- enter the following JavaScript formula
Image:John's Blog - XPages Example: Calling Java Methods directly from server side JavaScript - performing an SQL query Part 2

Last Steps:
- Add the JS library to the XPages.  On each XPage, select the Page properties, select the Resources tab and click Add Script Library.  Select the SQLFunctions library
- Drag a new Button Control to the page that will create new Employees
- Circle back to the Employee form and create the Save and Cancel buttons that will navigate back to the EmployeeView page.

That's it, your done!  Test it out.

Technorati:
(7)

PermaLink XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.06/29/2008 05:17 AM
Domino 8.5 - XPages
Below is an example of how to build a multi file upload Custom Control that uses a central attachment repository db for all the attachments.  The application has very little code and utilizes the Repeat control and Panel control to generate an unlimited amount of uploads per XPage.  (Actually, I am sure there is a limit but I have not hit it yet.)  The step by step instructions are below.  You can also download the example database(s) by clicking here: XPagesCustomControl.zip

*  Please Note: There's an updated version of this control Published on OpenNTF.org

Overview:

XPage Custom Controls allow you to build your own controls for reuse.  They show up in the control palette and can be dragged and dropped on any page just like any of the other controls.  The concept is similar to a subform in Domino.

I was demoing XPages to a group of colleagues the other day.  I was showing an example of the repeat control, which allows you to repeat a group of other controls based on a formula or value.  The neat thing about the Repeat control is it can dynamically creates controls at runtime.  One of the the guys asked about using the control to generate unlimited file upload controls for storage in central repository database.  I thought... wow, that is a great use case for an example (thanks Mark).  It was very quick to build too.

Let's start out with a look at the completed custom control:

Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.

After dropping it on an XPage, here is a screen shot of the control in use.  You can see that 3 files have been uploaded already and the user clicked the "Add New Upload" button a 4th time and is  presented with a blank upload control plus a description field:

Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.

The "Add New Upload" button creates a new document in the FileUploadDB database with a reference to the current document's doc ID. The page is then reloaded and the repeat control creates a new blank upload control bound to the new document. A simple JavaScript save() uploads the attachment.

You can drop this control anywhere on your page(s).  The only additional item that is needed on your page is a field calculating the document's docUNID (2nd to last screen shot below).


Here are the steps to build the control:

In your database, under Database Navigator select "Custom Controls" then click "New Custom Control".  Provide a name for the control.

Drag and drop a Button control on the page and for the label enter "Add New Upload".  Select the Event tab and provide the following formula for the onclick() event.  This will create a new attachment document in the repository and reload the page:

Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.
*note: for this example the attachment repository is named "FileUploadDB.nsf" in the Domino root directory

Next drag a Repeat control to the canvas.  Select JavaScript for the Iteration and enter the following for the  formula.  This formula looks up the associated attachments and generates an array of docIDs based on the document collection:
Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.

Enter the following for the Repeat control options. The "docid" variable will contain the docUNID for each document:
Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.
*note: I do limit the amount of uploads to 30.  I think that's enough...

Next drop a Panel control into the Repeat control.  Set the Datasource as follows:

Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.

Set the Document Id to be computed.  The Document ID will be the "docid" variable from the Repeat control:
Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.

There is one property we do have to set that is not obvious if you are starting out with XPages and Panels.  That is to: "ignoreRequestParams".  The reason for this is we are setting the Document ID and default Action for the Panel ourselves and do not want the Panel to pick up these parameters from the request.  Here is a screen shot of how to set that parameter:
Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.

Drop a "Table control" to the Panel, 1 row by 2 columns. Now we need to add our controls to the Table.  Add an "Edit Box", "File Upload" and "File Download".  Here's a screen shot of the bindings for the controls:

Description Edit Box Control:
Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.

FileUpload Control and FileDownload Control both have the same bindings:
Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.

For the FileUpload control we want to hide the control after one file has been uploaded.  We only want one attachment per repository document.  Here is a screen shot of the Visibility formula and where you would set that:
Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.

Set the opposite logic for the FileDownload control, that is return false if there are 0 attachments.

Place a Button control in the second column labeled "Upload".  Set the same visibilty formula as the FileUpload control.  It has a very simple formula which saves all data sources. You could substitute a simple action here if you prefer:

Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.


On the form where you will use the new MultiUpload control, I use the universalID for the link between the document and the attachment.  I placed a hidden Edit Box control on the page with the following Default value formula:
Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.

Lastly, here is the Attachment form in the FileuploadDB.nsf repository. I have a view sorted by ParentUNID named "vAttachmentLkUp":
Image:John's Blog - XPages Example: Building a Custom Control - How to build a Custom Multi-FileUpload Control that you can drop on any XPage, and it stores all attachments in an external repository db.

That's it!  It really is very minimal the amount of work involved.  It took less than an hour for me to do.  I am sure the interface could use a little bit more work, but I think it makes for a great example.

The one issue I had seemed to be a bug where I could not place the FileUpload control as the first control in the Panel.  I ended up putting the Description first and that seemed to fix the issue...very odd issue.  I posted the problem to the 8.5 Beta forum.

Download it and try it out.  Hopefully seeing these techniques solving a real business need will start you thinking about other uses for this technology.  Let me know if you have any questions....

John

Technorati:
(13)

PermaLink XPages Example: utilizing the built-in AJAX features06/22/2008 06:45 AM
Domino 8.5 - XPages
You can take advantage of AJAX while developing web 2.0 applications with XPages.  There are 2 features that provide built-in AJAX support.  

These are:
  • Ajax Type Ahead
  • Partial Page Refresh

Below I will walk you through step-by-step on how to implement these features in an application.  You can also download a sample database by clicking here: xPageAjaxExample.nsf

Ajax Type Ahead

The Ajax type ahead feature can be added to any edit box control.  It allows you to provide a list of values to the user by either entering a static list or computing the list via a formula.  There is also a choice for retrieving a list from a URL, though I have not tried this option myself.

In this screen shot I have clicked on an "Edit Box" control and then selected the "Type Ahead" tab:
- I clicked on "Enable Type Ahead"
- Selected "Full" mode
- For suggestions I selected computed and added a @DbColumn formula (next screen shot)
- I unchecked "Case-Sensitive"
* The help has a full description of the options

Image:John's Blog - XPages Example: utilizing the built-in AJAX features

For the type ahead suggestions, I want to return a list of Sales Representatives from a view.  I selected computed by clicking the diamond and entered the following formula:

Image:John's Blog - XPages Example: utilizing the built-in AJAX features

Here's the results if I enter the letter "s" in the SalesRep field in the browser.  The user is provided with a drop down of choices to select from:

Image:John's Blog - XPages Example: utilizing the built-in AJAX features




Ajax Partial Page Refresh

The partial page refresh is available on any event.  You select "Partial Update" on the event tab and then select the element you only want to have updated when the event is fired.  

In this example, I only want a table on the page to be updated when the user clicks the Lookup button.  Here is what the settings look like.  The table ID I want to refresh is "OtherCustomers":
Image:John's Blog - XPages Example: utilizing the built-in AJAX features

This is the screen shot prior to clicking the button.

Image:John's Blog - XPages Example: utilizing the built-in AJAX features

This is after the button is clicked.  Screen shots do not really do this feature justice, you'll need to try in in your browser to see the effect.
Image:John's Blog - XPages Example: utilizing the built-in AJAX features

This example is a very simple one where I have no business logic behind the button event.  The button's sole purpose is to force a round trip of the page to the server and provide the partial page refresh.  

There is a computed text field on the form that performs an @DbLookup based on the SalesRep field.  Here is the code for that computed field.  Note: I implode the array and use "<br>" as a separator so I get a line break.  On the computed field there is an option to set the "Content Type" as HTML.  This equates to pass thru HTML in Domino.  Here's the formula for the lookup:

Image:John's Blog - XPages Example: utilizing the built-in AJAX features

As you can see, it is very easy to take advantage of these 2 features.  Domino 8.5 also ships with the Dojo toolkit available on the server.  You will be able to utilize the library in you client side script for additional AJAX features.

Additional xPage examples on this site can be found here:  Domino 8.5 - XPages examples

John
Technorati:
(14)

PermaLink XPages Example part 2: Generating dynamic editable fields for a document collection06/16/2008 03:50 AM
Domino 8.5 - XPages
* please note: This example has been updated to work with 8.5 Gold.

I built on the previous XPage example, the Customer Orders application, to demonstrate how to generate dynamic fields from a document collection.  There is a sample database for you to download as well as a powerpoint presentation that explains the steps involved.

Over the years I have developed different techniques to handle dynamic fields in Domino applications.  I'm sure many of you have also tackled this issue in various ways.  In XPages there are built in controls that you can utilize to address this issue.

In the previous example I demonstrated how XPages allows you to bind your controls on the page to multiple datasources.  In this example I take it up a notch by showing how you can repeat a panel control that is bound to a document multiple times, thereby binding edit controls to a collection of Notes documents.  XPages maintains the binding so that all the documents are updated from a single button with a single simple action "Save Datasources".

Here's the use case: When a Customer Order is created there could be multiple items the customer is ordering.  We should give the user the ability to add new items dynamically by clicking a button.  The button will create a new response document and then reload the page.  The repeat control will generate the following editable fields for all the response documents: Item Number, Price, and Quantity.

Here is a screen shot:
Image:John's Blog - XPages Example part 2: Generating dynamic editable fields for a document collection

Here are the downloads:
- CustomerOrders.nsf
- step-by-step powerpoint

Download the application and try it out.  Contact me if you have any questions via posting or email.  My contact information is in the powerpoint.

John
Technorati:
(5)

PermaLink XPages Example: updating data from multiple forms from a single xPage06/09/2008
Domino 8.5 - XPages
* please note: This example has been updated to work with 8.5 Gold.

I put together an example of using XPages to update data from multiple forms on a single XPage.  There is a sample database for you to download as well as a presentation that walks you through the steps involved.

XPages separates the presentation layer from the data layer.  This is obviously very different to the one to one relationship in Domino.  XPages also allows the developer to bind to multiple datasources from a single page.  This feature can really provide a different approach to developing Domino applications.

I came up with the following simple use case:  We have an application where the user takes product orders that are shipped to customers.  Sometimes the user needs to update the customer information while taking the order.  We can provide the Customer fields right on the Order form and bind them via a Panel control to the Customer form.  A single button with a simple action saves all the bound datasources for the page and therefore updates both forms for us.  Here is a screen shot:

Image:John's Blog - XPages Example: updating data from multiple forms from a single xPage

Here are the downloads:
- CustomerOrders.nsf
- step-by-step powerpoint

Download the application and try it out.  Contact me if you have any questions via posting or email.  My email address is in the powerpoint (created with Symphony however!).

John
Technorati:
(12)

Search
Hire the Experts
Need help on your XPages projects?

Talk to the experts! Read more...
XPage Examples
By Category
About Me
Downloads
My Links
Monthly Archive
Powered by
Blogsphere
Lotus Domino ND7 RSS News Feed RSS Comments Feed Geo URL netcraft RSS Validator Lotus Geek Chris. A. Brandlehner OpenNTF BlogSphere