[Update 30-Mar-2019 there is a new version of IG Cookbook here]
Happy New Year. I wanted to get this IG Cookbook update out the same week that APEX version 5.1.4 was released and Early Adopter for 5.2 came out but a technical problem (described below) and the holidays slowed me down. I will have some things about 5.2 EA to blog about soon. Download IG Cookbook release 3.0. As always make sure you install the Sample Interactive Grid app first because it creates some needed tables.
The number of bug fixes to Interactive Grid has tapered off in this latest patch release. I would like to say it is because we have gotten to the bottom of the list of IG bugs but that is far from the case. It is because more and more focus has shifted to APEX 5.2 features. Still, great progress has been made on IG since its debut in 5.1 and you should upgrade to the latest if you are using IG in your apps. There are a few more IG bugs fixed in the early adopter of 5.2 so check that out and give feedback, but keep in mind there is plenty more bug fixing to be done before 5.2 is released.
One very important bug that was fixed in this latest patch is the No Data Found error that happened when you saved edits that caused a record to no longer match the where clause in the region SQL. The Cookbook showed a way to work around this bug on the Tasks (reorder) page. The work around is no longer needed so that page is updated but the original is still available in case someone wants to see the technique or hasn’t yet upgraded to 5.1.4.
This Cookbook has updated notes on some pages mostly to remove mention of issues that have been resolved. Two new pages have been added: Always Edit, and Rich Text and Custom Popup.
The most exciting new example page is Rich Text and Custom Popup. It started as a way to use the Rich Text Editor in IG (something a number of people have asked for) but grew into a general solution, the Custom Popup item plug-in, that could be useful in other contexts.
The reason that the Rich Text Editor can’t be used as a column item is that the grid widget moves the column item control between a hidden area and each cell as it receives focus (I described this here). The Rich Text Editor uses CKEditor which does the editing in an iframe. When an iframe is moved within the DOM the iframe source (src) is reevaluated which essentially destroys the CKEditor instance.
The general idea for a solution is to put the Rich Text Editor in a dialog that doesn’t move and the only part that does move is something that will popup the dialog. Once I started thinking about this I realized it was a general purpose solution. There are other cases where you want something like the Popup LOV item but you have special needs for how the value is selected/entered. Here are just a few examples of what could be done in a popup:
- Selecting a value using an IG or IR.
- Using an address validation service API to search for and select a correct postal address.
- Picking a point on a map to enter latitude and longitude.
In theory you would create a specific item plug-in for a specific popup data entry case. However some of the examples above would not be easy or are nearly impossible to encapsulate in an item plug-in. How would you create an item plugin that included an Interactive Report in a dialog without referencing an existing IR region on the page or re-implementing most of IR?
The issue is a lack of arbitrary composability in APEX. People with an Object Oriented background are used to being able to create new components as a composite of existing components through delegation and/or derivation. They may notice this as a defect of APEX but in practice it is rarely a serious problem. To be honest I have never heard an APEX developer complain about this.
The Custom Popup item lets you turn any inline dialog region you can create into a Popup LOV style item. The constraints on the dialog are that you must give it
setValue methods and set a custom dialog Boolean option
valueConfirmed to indicate when the user has accepted a value. See the * dlg add methods and OK button dynamic actions for how this is done.
The plug-in implements the text field and button that opens the dialog. It supports a display value distinct from the item value (like the “not enterable” Popup LOV). It basically handles all the details of being an item that works in a form or as a column in an IG plus the general details of opening and closing the popup dialog. You can have the dialog look like a normal dialog (centered on the page) or a popup attached to the input field.
The Rich Text and Custom Popup page has two examples of using the Custom Popup plug-in. One uses an Interactive Grid to select an employee. The other one uses a rich text editor to edit the notes column. Both examples have a display value but the rich text editor item has a strange use of the List of Values attribute that provides the display value. It isn’t used to “lookup” the display value but simply formats the value to remove markup and truncate it.
There were a number of challenges in getting the rich text editor item to work well in a dialog. The details can be seen in the dynamic actions related to adding methods, and opening and resizing the notes dialog. Resizing and focusing the editor was tricky because it may not have been initialized by the time the dialog is opened. This was fairly easy to figure out as was handling the escape key to close the dialog. The solution to various dialog interaction issues using dialog
_allowInteraction I found on the Internet. The problem that slowed me down had to do with focus events. In order to deactivate and activate cells for editing the IG needs to track focus movements. This gets tricky when the item uses a popup of its own where the focus will be completely outside of the grid widget. This is the purpose of the
getPopupSelector method. It lets IG know that the focus is still logically within the cell so that it doesn’t get deactivated. Because the rich text editor uses an iframe the focus event inside the iframe was not seen by the IG and the cell would get deactivated. This wasn’t a problem for updating the value but it caused focus to be lost when the dialog closed. It took me a while to find a solution. In hind sight it is simple. The focus event is propagated across the iframe boundary. The code for this is in the notes dlg add methods DA. It is also important to put focus on something in the dialog as soon as it opens.
Working through these issues has been very enlightening and may lead to improvements to the Rich Text Editor item in the future possibly even supporting it as a column item. Even if that happens I think there are still uses for the Custom Popup plug-in. This example page could use more testing especially in the area of accessibility. I also wanted to do some fancier filtering in the Select Manager dialog; maybe someday.
Some things I’m thinking of adding to the Custom Popup plug-in:
- An attribute for extra input items to pass to the dialog.
- An attribute for extra output to return from the dialog that set additional items.
- Accessibility improvements. It seems something should be done with the button label when there is no button.
- Changing the Has Display Value attribute to make it more clear how to use it to format the value like is done in the rich text case.
You can take the Custom Popup plug-in and use it in your own apps. If you come up with an interesting use case for it I would love to hear about it.
Feel free to discus the techniques shown in this app or issue with this app on the APEX Discussion Forum. This is not an officially supported sample but I’ll reply if possible and you can all help each other as well.