I also discovered today that the extension library dialog control <xe:dialog> can be modified to act as a bootstrap modal dialog. See this link on the new site http://bootstrap4xpages.com by Mark Leusink for more details. I really wish I saw this post earlier, but since I already built what I did, I am going to stay with it.
The way this works is that the calling xpage (New_PO) has a button which the user presses to begin the first step in the process. The button starts by launching an xpage that holds the modalWindow custom control. The control is automatically launched so that it appears to the user that it opens automatically. In actuality, I have an unnamed button that is launched using jQuery upon page load. This works really well. Here is the very simple code:
Note that there is one of these 'shell' xpages for each step in the wizard. They are needed because you can't link to a custom control, that really doesn't make sense. There is one shell xpage per step and they are all the exact same code with the exception of the custom properties.
Since the last few posts, I have needed to make several modifications to fit my current project. These are the changes I made to the modalWindow custom control.
- Removed slide effect from the modal window. The effect, although cool, was a bit of an eye strain, and more importantly caused vertical centering issues on a mobile user agent. I changed it the button class from to
- Prevented the user from closing the dialog by using the escape key. This is done by adding data-keyboard="false" to the button or anchor that launches the modal window.
- Likewise, I needed to prevent the window from closing when they click off the window. This is done by adding data-backdrop="static" to the button or anchor.
- Added new custom control property definitions for the nextXPage, and the cancelXPage. The nextXPage controls which xpage is opened next, and the cancelXPage property takes it back to the beginning xpage. Without it, the user would be taken to the xpage containing the launch button that they are not intended to ever see. I will need to add a SSJS function to these as well going forward to process the contents of each window. UPDATE: I figured out how to add SSJS functions to process the contents of each window, see this post.
I think this solution will be fairly portable, and it is not as complicated as it seems. Here is a drawing to illustrate. The blue area is where I begin to develop application specific input fields. The blue area is where the application specific code will go, the rest will work for any app using this technique (with the exception of the six custom properties).