{"id":1234,"date":"2021-10-11T09:20:12","date_gmt":"2021-10-11T14:20:12","guid":{"rendered":"https:\/\/hardlikesoftware.com\/weblog\/?p=1234"},"modified":"2021-11-04T14:39:44","modified_gmt":"2021-11-04T19:39:44","slug":"apex-21-2-new-javascript-apis-joelkallmanday","status":"publish","type":"post","link":"https:\/\/hardlikesoftware.com\/weblog\/2021\/10\/11\/apex-21-2-new-javascript-apis-joelkallmanday\/","title":{"rendered":"APEX 21.2 New JavaScript APIs #JoelKallmanDay"},"content":{"rendered":"<p>It shouldn\u2019t be long now before the next release of Oracle APEX, 21.2, is available on <a href=\"https:\/\/apex.oracle.com\" rel=\"noopener noreferrer\" target=\"_blank\">apex.oracle.com<\/a>. There will be plenty of buzz around the big new features in 21.2 but here I\u2019ll introduce some new client side APIs and along the way I\u2019ll mention some of the new or recent features the APIs apply to.<\/p>\n<p>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\u2019t all fit in one blog so <a href=\"https:\/\/twitter.com\/stefan__dobre\" rel=\"noopener noreferrer\" target=\"_blank\">Stefan Dobre<\/a> is going to tell you about <a href=\"https:\/\/stefandobre.com\/2021\/10\/11\/javascript-api-enhancements-in-apex-21-2-joelkallmanday\/\/\" rel=\"noopener noreferrer\" target=\"_blank\">some of it<\/a>.<\/p>\n<p><!--more--><\/p>\n<p>When you scan the 21.2 JavaScript API documentation index you will notice 2 new namespaces and 4 new interfaces.<\/p>\n<p>New namespaces:<\/p>\n<ul>\n<li>apex.date<\/li>\n<li>apex.pwa<\/li>\n<\/ul>\n<p>New interfaces:<\/p>\n<ul>\n<li>colorPickerItem<\/li>\n<li>facetsRegion<\/li>\n<li>mapRegion<\/li>\n<li>numberFieldItem<\/li>\n<\/ul>\n<p>[Update 4-Nov: APEX 21.2 is released and the API doc can be found <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/application-express\/21.2\/aexjs\/index.html\" rel=\"noopener\" target=\"_blank\">here<\/a>.]<\/p>\n<h2>New Namespaces<\/h2>\n<p>The <code>apex.pwa<\/code> 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\u2019t 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.<\/p>\n<p>The <code>apex.date<\/code> 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. <\/p>\n<p>For example this will add 2 days to today\u2019s date.<\/p>\n<pre class=\"code\"><code>apex.date.add( new Date(), 2, apex.date.UNIT.DAY );\r\n<\/code><\/pre>\n<p>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 <a href=\"https:\/\/blog.danielhochleitner.de\/2021\/10\/11\/new-apex-date-js-api-in-apex-21-2\/\" rel=\"noopener noreferrer\" target=\"_blank\">details<\/a>]<\/p>\n<h2>New Region Interfaces<\/h2>\n<p>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 <a href=\"https:\/\/hardlikesoftware.com\/weblog\/2015\/04\/29\/apex-5-0-page-designer-meet-the-widgets\/\" rel=\"noopener noreferrer\" target=\"_blank\">APEX 5.0<\/a> we started to make a big investment in native components based on the <a href=\"https:\/\/jqueryui.com\/\" rel=\"noopener noreferrer\" target=\"_blank\">jQuery UI<\/a> 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 <a href=\"https:\/\/hardlikesoftware.com\/weblog\/2016\/06\/08\/interactive-grid-under-the-hood\/\" rel=\"noopener noreferrer\" target=\"_blank\">new widgets<\/a>. 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\u2019t worry we can\u2019t remove jQuery UI anytime soon. The reality is that we can\u2019t 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\u2019t change that.)<\/p>\n<p>For those that don\u2019t care about the particulars of what 3rd party libraries we use and just need to &#8220;get the job done&#8221; 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:<\/p>\n<pre class=\"code\"><code>$( selector ).widgetName( \"methodName\", args );\r\n<\/code><\/pre>\n<p>A more normal looking method call would be:<\/p>\n<pre class=\"code\"><code>widgetObject.methodName( args );\r\n<\/code><\/pre>\n<p>This brings us to the new region interfaces. I\u2019ll use <code>facetsRegion<\/code> 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 <a href=\"https:\/\/hardlikesoftware.com\/weblog\/2020\/11\/22\/apex-fancy-facets\/\" rel=\"noopener noreferrer\" target=\"_blank\">became clear<\/a>. 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.<\/p>\n<p>To see what this looks like lets compare how you call an interactiveGrid method with how you call a new facetsRegion method. <\/p>\n<p>If you wanted to get the currently selected records from IG you would do this:<\/p>\n<pre class=\"code\"><code>var records = apex.region(\"regionid\").call(\"getSelectedRecords\");\r\n<\/code><\/pre>\n<p>Or using the older and more verbose syntax:<\/p>\n<pre class=\"code\"><code>var records = apex.region(\"regionid\").widget().interactiveGrid(\"getSelectedRecords\");\r\n<\/code><\/pre>\n<p>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 <code>getFacetCount<\/code> method is used as follows:<\/p>\n<pre class=\"code\"><code>var count = apex.region(\"regionId\").getFacetCount();\r\n<\/code><\/pre>\n<p>Note that there is no need for <code>call<\/code> or <code>widget<\/code> or the widget name or putting the method name in quotes. Its just a good old fashioned JavaScript method call.<\/p>\n<p>Accessing a property is also much simpler; no more &#8220;option&#8221; method. The <code>facetsRegion<\/code> has a property (think of it like an option) called <code>maxChips<\/code>. You can get and set the value like this:<\/p>\n<pre class=\"code\"><code>\/\/ get\r\nvar value = apex.region( \"regionId\" ).maxChips;\r\n\/\/ set\r\napex.region( \"regionId\" ).maxChips = 4;\r\n<\/code><\/pre>\n<p>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.<\/p>\n<p>Back to that <code>maxChips<\/code> 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. <\/p>\n<figure id=\"attachment_1242\" aria-describedby=\"caption-attachment-1242\" style=\"width: 1003px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" src=\"https:\/\/hardlikesoftware.com\/weblog\/wp-content\/uploads\/2021\/10\/js_api_212_SmartSearch.png\" alt=\"Smart Filters UI\" width=\"1003\" height=\"130\" class=\"size-full wp-image-1242\" srcset=\"https:\/\/hardlikesoftware.com\/weblog\/wp-content\/uploads\/2021\/10\/js_api_212_SmartSearch.png 1003w, https:\/\/hardlikesoftware.com\/weblog\/wp-content\/uploads\/2021\/10\/js_api_212_SmartSearch-300x39.png 300w, https:\/\/hardlikesoftware.com\/weblog\/wp-content\/uploads\/2021\/10\/js_api_212_SmartSearch-768x100.png 768w\" sizes=\"(max-width: 1003px) 100vw, 1003px\" \/><figcaption id=\"caption-attachment-1242\" class=\"wp-caption-text\">New Smart Filters Region<\/figcaption><\/figure>\n<p>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.<\/p>\n<p>The <code>mapRegion<\/code> 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\u2019t 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.<\/p>\n<p>For example you might want to set the map zoom level from a dynamic action with code such as:<\/p>\n<pre class=\"code\"><code>apex.region( \"regionId\" ).setZoomLevel( 3 );\r\n<\/code><\/pre>\n<p>We say that the interfaces <code>mapRegion<\/code> and <code>facetsRegion<\/code> <em>extend<\/em> the <code>region<\/code> 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 <em>base<\/em> 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.<\/p>\n<p>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 <code>refresh<\/code> method that typically means to get fresh data from the server and display it. The convention for jQuery UI widgets is to have a <code>refresh<\/code> method but it only refreshes the DOM (sometimes necessary after changing configuration options) it doesn\u2019t necessarily get new data from the server. The solution for these new region interfaces is that <code>refresh<\/code> 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 <code>refreshView<\/code> method (which is what the jQuery UI widget would call refresh).<\/p>\n<p>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:<\/p>\n<pre class=\"code\"><code>apex.region(\u201cstaticid\u201d).fetchCounts(). \r\n<\/code><\/pre>\n<p>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.<\/p>\n<h2>New Item Interfaces<\/h2>\n<p>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 <code>addValue<\/code> 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 <code>numberFieldItem<\/code> item that extend the item interface. A <code>numberFieldItem<\/code> is a more specific kind of item. It has the same methods and properties of an item except that the ones that don\u2019t apply are not documented\/used.<\/p>\n<p>When you call <code>apex.item(\"itemid\")<\/code> 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 <code>getNativeValue<\/code>. But now these extras are documented.<\/p>\n<p>The additional method offered by the <code>numberFieldItem<\/code> is <code>getNativeValue<\/code> which returns a JavaScript number rather than a string like <code>getValue<\/code> does. This method is very useful if you want to do some client side math on the value of a Number Field.<\/p>\n<p>The additional methods offered by the <code>colorPickerItem<\/code> are:<\/p>\n<ul>\n<li><code>getNativeValue<\/code> which returns an object with properties for the red, green, blue, and alpha values and<\/li>\n<li><code>contrastWith<\/code> which is used to compare the color value of this item with another color and return contrast information.<\/li>\n<\/ul>\n<p>The still newish Date Picker item also has a <code>getNativeValue<\/code> method but there wasn\u2019t time to add it to the documentation.<\/p>\n<p>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.<\/p>\n<p>Another thing for plug-in developers related to improvements to the region and item interfaces is the <code>apex.region.create<\/code> and <code>apex.item.create<\/code> 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. <\/p>\n<h2>Future Direction<\/h2>\n<p>You may be wondering what will happen to the existing widget style APIs such as <code>grid<\/code> and <code>menu<\/code> 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.)<\/p>\n<p>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:<\/p>\n<pre class=\"code\"><code>var records = apex.region(\"regionid\").getSelectedRecords(); \/\/ doesn't work yet\r\n<\/code><\/pre>\n<p>Where it get more interesting is, for example, with the grid widget because it is accessed from the <code>interactiveGridView<\/code> interface and isn&#8217;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.<\/p>\n<h2>Odds and Ends<\/h2>\n<p>That covers all the big changes. Other things to check out once the API doc is available include:<\/p>\n<ul>\n<li>The template processing documented in <code>apex.util.applyTemplate<\/code>. The <code>{if\/}<\/code> 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 method <code>apex.util.escapeHTMLAttr<\/code> is added.<\/li>\n<li>The item interface for items that use <code>delayLoading<\/code> (for example the JET based Date Picker item takes a little longer to load) now give you methods <code>isReady<\/code> and <code>whenReady<\/code> to check if the item is ready and wait for it to become ready respectively.<\/li>\n<li>Don\u2019t forget to check out <a href=\"https:\/\/stefandobre.com\/2021\/10\/11\/javascript-api-enhancements-in-apex-21-2-joelkallmanday\/\" rel=\"noopener noreferrer\" target=\"_blank\">Stefan\u2019s blog<\/a> for more cool API features.<\/li>\n<\/ul>\n<p>Also note that desupported APIs have been removed from the documentation. Some of them were moved to the legacy JavaScript file <code>legacy_18.js<\/code>. This means that if you are still using desupported APIs you may need to check the box to have <code>legacy_18.js<\/code> loaded. Go to the Edit Application Definition page User Interface tab and check the 18.x checkbox.<\/p>\n<p><img loading=\"lazy\" src=\"https:\/\/hardlikesoftware.com\/weblog\/wp-content\/uploads\/2021\/10\/js_api_212_legacyconfig.png\" alt=\"Legacy API config\" width=\"570\" height=\"97\" class=\"aligncenter size-full wp-image-1246\" srcset=\"https:\/\/hardlikesoftware.com\/weblog\/wp-content\/uploads\/2021\/10\/js_api_212_legacyconfig.png 570w, https:\/\/hardlikesoftware.com\/weblog\/wp-content\/uploads\/2021\/10\/js_api_212_legacyconfig-300x51.png 300w\" sizes=\"(max-width: 570px) 100vw, 570px\" \/><\/p>\n<p>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.<\/p>\n<p>As always check the release notes (once available) for details about what is new and what has changed.<\/p>\n<p>I hope you enjoy these new APIs with simpler syntax. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>It shouldn\u2019t 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<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/hardlikesoftware.com\/weblog\/2021\/10\/11\/apex-21-2-new-javascript-apis-joelkallmanday\/\">Continue reading<span class=\"screen-reader-text\">APEX 21.2 New JavaScript APIs #JoelKallmanDay<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[18,13],"tags":[41,65],"_links":{"self":[{"href":"https:\/\/hardlikesoftware.com\/weblog\/wp-json\/wp\/v2\/posts\/1234"}],"collection":[{"href":"https:\/\/hardlikesoftware.com\/weblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hardlikesoftware.com\/weblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hardlikesoftware.com\/weblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hardlikesoftware.com\/weblog\/wp-json\/wp\/v2\/comments?post=1234"}],"version-history":[{"count":22,"href":"https:\/\/hardlikesoftware.com\/weblog\/wp-json\/wp\/v2\/posts\/1234\/revisions"}],"predecessor-version":[{"id":1259,"href":"https:\/\/hardlikesoftware.com\/weblog\/wp-json\/wp\/v2\/posts\/1234\/revisions\/1259"}],"wp:attachment":[{"href":"https:\/\/hardlikesoftware.com\/weblog\/wp-json\/wp\/v2\/media?parent=1234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hardlikesoftware.com\/weblog\/wp-json\/wp\/v2\/categories?post=1234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hardlikesoftware.com\/weblog\/wp-json\/wp\/v2\/tags?post=1234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}