Last updated on Thursday, November 4, 2021
It shouldn’t be long now before the next release of Oracle APEX, 21.2, is available on apex.oracle.com. There will be plenty of buzz around the big new features in 21.2 but here I’ll introduce some new client side APIs and along the way I’ll mention some of the new or recent features the APIs apply to.
This release has the biggest set of additions to the JavaScript APIs since 19.1 when the new JSDoc based API documentation became official. There is enough cool new stuff that it won’t all fit in one blog so Stefan Dobre is going to tell you about some of it.
When you scan the 21.2 JavaScript API documentation index you will notice 2 new namespaces and 4 new interfaces.
New namespaces:
- apex.date
- apex.pwa
New interfaces:
- colorPickerItem
- facetsRegion
- mapRegion
- numberFieldItem
[Update 4-Nov: APEX 21.2 is released and the API doc can be found here.]
New Namespaces
The apex.pwa
namespace is part of the new Progressive Web App (PWA) feature. PWAs are a broad topic well beyond the scope of this blog. This is the first APEX release with any PWA support and the focus is on installation. Installing a web app gives a more native app experience with an icon on the desktop and better performance by caching some static files. You most likely won’t need to use any of these APIs but if you have a desire to customize the installation UI the functions in this namespace should be helpful.
The apex.date
namespace is interesting because it is available and documented before APEX even makes use of it. It is added with the intention of using it to enhance the calendar and other components in the future. In the mean time you should find a number of useful functions in there for working with dates.
For example this will add 2 days to today’s date.
apex.date.add( new Date(), 2, apex.date.UNIT.DAY );
There are many other goodies in there including formatting and parsing using a subset of Oracle Database date format model patterns. Unlike the moment.js library apex.date uses native JavaScript Date objects. If you are using moment.js you should consider switching to use apex.date. (moment.js is still included as part of jquery fullcalendar 3.x but that could change in the future.) [Update: Daniel has more details]
New Region Interfaces
The main thing I want to explain is the new interfaces and how they represent a new direction for item and region APIs. Back in APEX 5.0 we started to make a big investment in native components based on the jQuery UI widget factory pattern. Back then it was a reasonable choice but not one that anyone would make today. In APEX 5.1 we added the interactive grid region that was implemented with a number of new widgets. By APEX19.1 many of these widget APIs were documented. Then in release 20.1 we deprecated jQuery UI, which caused some confusion. The response to that confusion has mostly been don’t worry we can’t remove jQuery UI anytime soon. The reality is that we can’t snap our fingers and instantly port all our code to some new UI library (the APEX team has grown but not that much) so the APEX dependency on jQuery UI will remain for some time. But ideally our APIs should be independent from it. (In case it is not clear why we deprecated jQuery UI, it is because it is not an actively maintained library. The coincidental fact that a new version was released a few days ago doesn’t change that.)
For those that don’t care about the particulars of what 3rd party libraries we use and just need to “get the job done” they may have found what they need in our API documentation but thought the syntax a little odd. Indeed jQuery UI widget APIs do seem strange:
$( selector ).widgetName( "methodName", args );
A more normal looking method call would be:
widgetObject.methodName( args );
This brings us to the new region interfaces. I’ll use facetsRegion
as an example. The faceted search region introduced in release 19.2 happens to implement the UI as a widget using jQuery UI. But this is just an implementation detail that should not concern you. Initially there was no need to document this widget but as we added more features and people found unique use cases the need for a documented API became clear. Now that jQuery UI is deprecated it would make no sense to introduce a new widget style API. There is also no value to our customers in re-implementing facets UI to not use jQuery UI. The solution is a light weight wrapper around the widget API exposed as an extension of the APEX region interface.
To see what this looks like lets compare how you call an interactiveGrid method with how you call a new facetsRegion method.
If you wanted to get the currently selected records from IG you would do this:
var records = apex.region("regionid").call("getSelectedRecords");
Or using the older and more verbose syntax:
var records = apex.region("regionid").widget().interactiveGrid("getSelectedRecords");
Faceted Search is a very different kind of region; it has no selected records but one thing you may want to do is find out how many facets the user has selected. For this the getFacetCount
method is used as follows:
var count = apex.region("regionId").getFacetCount();
Note that there is no need for call
or widget
or the widget name or putting the method name in quotes. Its just a good old fashioned JavaScript method call.
Accessing a property is also much simpler; no more “option” method. The facetsRegion
has a property (think of it like an option) called maxChips
. You can get and set the value like this:
// get
var value = apex.region( "regionId" ).maxChips;
// set
apex.region( "regionId" ).maxChips = 4;
This is clearly friendlier syntax but more important it separates the documented API from the implementation details. It allows us to change the internal implementation without breaking the API.
Back to that maxChips
property. If you are familiar with the faceted search functionality you may be scratching your head wondering what maxChips relates to. One of the big new features in 21.2 is a new region called Smart Filters. This is a brand new UI pattern from the Oracle Redwood Design Team. Its purpose is similar to faceted search but the UI is modern and compact.
Because smart filters has so much in common with faceted search the same code is shared between them on both the back end and in the UI. So the facetsRegion API (and internally the facets widget) handles both the faceted search region and the new smart filters region. Some properties apply to both regions and some are specific to just one. In the screen shot above, the boxes below the search field are call suggestion chips and the maxChip property lets you configure how many to show. You will not likely ever need this property because it is also a declarative option. In fact almost all functionality of smart filters and faceted search is declarative. But it is nice to have a documented API for the edge cases where it is needed. I hope to have an updated sample to demonstrate Smart Filters in the future. This API will also be useful in the future where we hope to make it possible for region plug-ins to integrate with faceted search and smart filters the way that native regions such as Cards and Classic Reports do.
The mapRegion
has a similar story. In release 21.1 the Maps region was introduced. It is fairly common to need to customize the UI for Maps. In fact the Sample Maps application shows a few examples that use the undocumented old-style widget API. This was done out of necessity even though we knew it was another case were we didn’t want to document a new jQuery UI style API. So now the mapRegion also extends the region interface. I expect at some point the sample will be updated to use the new documented API.
For example you might want to set the map zoom level from a dynamic action with code such as:
apex.region( "regionId" ).setZoomLevel( 3 );
We say that the interfaces mapRegion
and facetsRegion
extend the region
interface. This means that a mapRegion or a facetsRegion is a more specific kind of region. It will have the same methods and properties as the base region plus some extra ones. Note some of the region methods or properties may not apply to the more specific region interfaces and therefore are not available.
There was one area of conflict between the region interface and the typical jQuery UI widget that had to be resolved. The region interface has a refresh
method that typically means to get fresh data from the server and display it. The convention for jQuery UI widgets is to have a refresh
method but it only refreshes the DOM (sometimes necessary after changing configuration options) it doesn’t necessarily get new data from the server. The solution for these new region interfaces is that refresh
means get and display data from the server. It is still up to the particular region to determine if refresh is supported and the details of what gets refreshed. If a region has the need to refresh just the DOM (a.k.a the view or UI) then it may have a refreshView
method (which is what the jQuery UI widget would call refresh).
This explains a change in behavior between the old undocumented region interface for faceted search and the new facetsRegion interface. Prior to 21.2 if you wanted to refresh the counts data of the faceted search region you would call the undocumented fetchCounts method like this:
apex.region(“staticid”).fetchCounts().
Now you can call the more intuitive and standard refresh method and whats more it means that the Dynamic Action Refresh action will work as expected for the faceted search region.
New Item Interfaces
For the longest time item interfaces returned by apex.item() all had the exact same methods and properties. Even if some of those methods such as addValue
only applied to a very few item types. Starting a few release ago item plug-in implementations could extend the base methods and properties. So in the same way that the mapRegion extends the region interface we now have specific items like the numberFieldItem
item that extend the item interface. A numberFieldItem
is a more specific kind of item. It has the same methods and properties of an item except that the ones that don’t apply are not documented/used.
When you call apex.item("itemid")
you get back an item interface that is specific to the type of item it is. This was true even in release 21.1 where, for example, the interface for a Number Field item had the extra method getNativeValue
. But now these extras are documented.
The additional method offered by the numberFieldItem
is getNativeValue
which returns a JavaScript number rather than a string like getValue
does. This method is very useful if you want to do some client side math on the value of a Number Field.
The additional methods offered by the colorPickerItem
are:
getNativeValue
which returns an object with properties for the red, green, blue, and alpha values andcontrastWith
which is used to compare the color value of this item with another color and return contrast information.
The still newish Date Picker item also has a getNativeValue
method but there wasn’t time to add it to the documentation.
For item and region plug-in developers it should be clear that you can add your own properties and methods to extend the base item and region interfaces.
Another thing for plug-in developers related to improvements to the region and item interfaces is the apex.region.create
and apex.item.create
functions now allow passing in a function rather than an object to define the interface. The API documentation has examples of what this looks like. The purpose is that in some cases it is more efficient and flexible to add to the base instance rather than passing in an object that then has to be merged with (copied to) the base instance object.
Future Direction
You may be wondering what will happen to the existing widget style APIs such as grid
and menu
that we have already documented. They are not deprecated and will likely remain supported for a long time. There may be a time when essentially the same functionality is available as a widget style API and a region interface style API. (You can still use the jQuery UI style API with the mapRegion or facetedSearch region as long as the method and property names are the same. This is good for backward compatibility but I expect everyone will want to switch to the newer, friendlier, documented API.)
For example it may be in the future that you will be able to get the selected records from an interactive grid region with code such as the following:
var records = apex.region("regionid").getSelectedRecords(); // doesn't work yet
Where it get more interesting is, for example, with the grid widget because it is accessed from the interactiveGridView
interface and isn’t currently a standalone region. The details are still being figured out. We will continue to improve our code base, which is reflected in our APIs, as we also deliver on new features.
Odds and Ends
That covers all the big changes. Other things to check out once the API doc is available include:
- The template processing documented in
apex.util.applyTemplate
. The{if/}
directive has been updated so that you can distinguish an empty/null test from a Boolean Y/N test. Some of the documentation for applyTemplate was improved and clarified. The output escaping for attribute substitutions was improved and a new methodapex.util.escapeHTMLAttr
is added. - The item interface for items that use
delayLoading
(for example the JET based Date Picker item takes a little longer to load) now give you methodsisReady
andwhenReady
to check if the item is ready and wait for it to become ready respectively. - Don’t forget to check out Stefan’s blog for more cool API features.
Also note that desupported APIs have been removed from the documentation. Some of them were moved to the legacy JavaScript file legacy_18.js
. This means that if you are still using desupported APIs you may need to check the box to have legacy_18.js
loaded. Go to the Edit Application Definition page User Interface tab and check the 18.x checkbox.
Or even better remove any uses of deprecated APIs from your code. Because of some dependencies between the old APIs and even older ones you may find that if you previously only had Pre 18.1 checked you may now need to check 18.x as well.
As always check the release notes (once available) for details about what is new and what has changed.
I hope you enjoy these new APIs with simpler syntax.
[…] Read more about the new JS API enhancements in the blog post from Stefan Dobre here and the one from John Snyders here. […]
Hi John (and Team),
Since coming from the backend (PL/SQL) I have always wondered: why do these js calls (the syntax) have to be so complicated.
Why can’t this be done more simply?
Now I see: Well it can be much simpler; it’s obvious, precise and clear.
My panic about js is slowly subsiding… 🙂
Thanks! And keep up the good work!
Regards
André
Great explanation!