While exploring the use of Oracle JET to enhance the UI capabilities of PeopleSoft Fluid, we saw how we could employ basic
responsive layout/styling (Alta UI css) and
data binding (KnockoutJS) functionality.
Based on what we learned so far, does it appear like PeopleTools natively (via App Designer) support Oracle JET? Probably not. But are there enough built-in functions/tools/workarounds to integrate Oracle JET with Fluid UI? Yes, yes and yes!
In this post, I will demonstrate how we can integrate an
Oracle JET - Visualization Component (Status Meter Gauge) in a Fluid page to enrich the UI (more than what we could normally achieve within the confines of App Designer). By the way, this post is inspired by the
Oracle JET MOOC -
Lesson 2 - Part 2: Data Visualization Components. I highly recommend watching the video to get an understanding of the Status Meter Gauge. We will try to replicate the following behavior demonstrated on an
Oracle JET QuickStart Template website (see oj Module section in the below animation).
Development Environment: HCM 9.2 PUM Image 17 - PeopleTools 8.55.03
Assumptions: For the purposes of this demo, it is assumed that the
latest version of Oracle JET is installed on the web server.
Step 1: Add Oracle JET paths to requireJS configuration
If we work with the Oracle JET QuickStart Template (especially using NetBeans), we will realize that the entire framework to develop and run Oracle JET applications is pre-configured for us. So there is not much we have to do other than plug and play the modules, components, etc.
As part of the pre-configured framework, the requireJS config for the QuickStart Template can be found in the main.js:
Because we are trying to wire this into the PeopleSoft architecture,
we need to make sure the Oracle JET related libraries are added to the
requireJS path configuration. So, let us update our global requireJS configuration to include the following Oracle JET paths.
'knockout': cskBowerCompsPath+'/knockout/dist/knockout',
'ojs':cskBowerCompsPath+'/oraclejet/dist/js/libs/oj/debug',
'ojL10n':cskBowerCompsPath+'/oraclejet/dist/js/libs/oj/ojL10n',
'ojtranslations':cskBowerCompsPath+'/oraclejet/dist/js/libs/oj/resources',
'promise':cskBowerCompsPath+'/es6-promise/promise.min',
'ojdnd':cskBowerCompsPath+'/oraclejet/dist/js/libs/dnd-polyfill/dnd-polyfill-1.0.0.min',
'jqueryui-amd':cskBowerCompsPath+'/jquery-ui/ui/minified',
'signals':cskBowerCompsPath+'/js-signals/dist/signals.min'
For complete javascript code, please refer jsFiddle link:
CSK_REQUIRE_CFG_JS
Note:
- The library paths for Oracle JET (installed using bower or direct download) might not be the same as what we normally find in the Oracle JET QuickStart Template. Please make sure the paths are referenced appropriately.
- For more details on using requireJS refer: PeopleTools 8.55+ - Using Oracle JET (JQuery, JQueryUI, requireJS and more):
Part 1,
Part 2,
Part 3,
Part 4
Step 2: Create a Fluid Page
Let us create a simple Fluid page - CSK_OJ_GAUGE_DEMO - using PSL_APPS_CONTENT layout. And add a couple of group boxes for creating a flex layout (
oj-flex and
oj-flex-item). Adding the flex layout is optional but you can refer to
Fluid UI - Oracle JET - Using Oracle Alta UI and Flex Layouts for more details.
Further, let us add the following page field elements:
Group Box (Layout Only to group page field elements):
Edit Box (Input Field):
This field will represent the 'Sales Percentage' input element for our demonstration.
Group Box (Layout Only placeholder for the ojStatusMeterGauge component):
This is just a
placeholder group box to generate the DIV where we will eventually add the
ojStatusMeterGauge "View" data-bind attributes. Notice the 'Override PeopleTools Style?' is selected? This is to ensure that none of the delivered styles will interfere with this element.
Push Button (To Send Gauge/Input value back to PeopleSoft):
The reason why we have this push button here is to demonstrate how Oracle JET integrates with the PeopleSoft architecture (PIA). We will evaluate how certain events on the page ("View") might possibly disturb (mutate) the knockout bindings and how we can work around those issues.
Note: There may be more efficient ways (than the methods described) to workaround these
quirks and I would be happy to hear from others on this topic! Please feel free to leave a comment.
Step 3: Add the ojStatusMeterGauge related data binding to the View (Page HTML)
As shown in the
MOOC lesson, we will be using the div on line 252 from this
Oracle JET - Cookbook - HTML code for the Status Meter Gauge. Let us adjust the attribute values slightly (to give an appropriate custom
value (cskValue) for the data-bind and to update the style
margin to work effectively on our Fluid page).
HTML:
ojStatusMeterGauge Component DIV
Now, we need to apply the data-bind and style attributes from the above sample DIV to the
gauge-container group box on our Fluid page.We can do that with the following Page Activate PeopleCode. While we are at it, we can also add the data-bind attribute to the edit box (input field). This is specifically to establish a two way data-bind between the
gauge and the
input field.
PeopleCode For Reference:
Declare Function SetViewport PeopleCode PTLAYOUT.FUNCLIB FieldFormula;
/* Set ViewPort Meta for SFF Scaling */
SetViewport("width=device-width,user-scalable=yes,initial-scale=1.0,minimum-scale=1.0"); /* apply the system default viewport setting */
/* Setting the data-binds in the "View" */
CSK_OJ_WRK.GROUPBOX.HtmlAttributes = "data-bind=""ojComponent: {component: 'ojStatusMeterGauge', min: 0, max: 100, value: cskValue, orientation: 'circular', plotArea: {rendered: 'on'}, metricLabel: {rendered: 'on'}, title: {text: 'Sales'}, readOnly: false}"" style=""margin: 5px auto; height:100px; width:45%;""";
CSK_OJ_WRK.PERCENT_COMPLETE.HtmlAttributes = "data-bind=""value: cskValue""";
Step 4: Apply Knockout Bindings to the ViewModel
Let us update the PageActivate PeopleCode to include a javascript object
(CSK_OJ_GAUGE_MAIN_JS) on page load. This javascript will serve the same
purpose as a traditional 'main.js' in the javascript/Oracle JET
architecture.
JavaScript:
CSK_OJ_GAUGE_INIT_JS
The reason I introduced this new javascript object (CSK_OJ_GAUGE_INIT_JS) is because if we create global variables in the CSK_OJ_GAUGE_MAIN_JS which is loaded as an
AddOnLoadScript, the variables would not persist and appear as
undefined subsequently. As a workaround, CSK_OJ_GAUGE_INIT_JS was created and loaded using the
AddJavaScript function instead of
AddOnLoadScript function - prior to the execution of our main.
JavaScript:
CSK_OJ_GAUGE_MAIN_JS
- As you can see, we added the requireJS configuration path to the "ViewModel" javascript in
the main (CSK_OJ_GAUGE_MAIN_JS), instead of using the global requireJS configuration in Step 1 (while setting up Oracle JET paths). This is because we do not want this app (page) specific path to clutter our global
requireJS configuration.
- In the require block, we injected the Alta css to enable the
oj-flex and
oj-flex-item styling that we used in Step 2.
- Then, the Knockout bindings are applied to the "ViewModel" which resides in CSK_OJ_GAUGE_VIEWMODEL_JS.
- The cskOJKORefresh function was created to take care of page events that might require a server trip (e.g.: Clicking on 'Send To Server' button would trigger the FieldChange event). Since PeopleSoft automatically reloads the page field element(s) on every server trip, we will find that the Knockout data-bindings are lost when such events are triggered. For more details on this quirk, click
here.
Step 5: Create ViewModel JavaScript Object - CSK_OJ_GAUGE_VIEWMODEL_JS
JavaScript:
CSK_OJ_GAUGE_VIEWMODEL_JS
- The define block for the ViewModel includes all the Oracle JET libraries that are dependencies (including knockout) for
ojgauge.
- The subscribe function on
cskValue calls the delivered
addchg_%formname function to take care of a PeopleSoft quirk once again. After a server trip, if we don't highlight/activate the edit box (
input field) and simply use the
gauge to modify the value, then the new value will not get propagated to the server subsequently via the component buffer (
input field). This function tricks/forces the component buffer to notice the change in the
input field value. For more details on this quirk, click
here.
Step 6: Create the FieldChange PeopleCode Event
This code will take care of handling the 'Send To Server' push button event.
- The FieldChange event on the server side simply returns a confirmation message with the value it received for the Sales Percentage.
- Additionally, the cskOJKORefresh javascript function is invoked as part of this PeopleCode event to take care of the
quirk mentioned in Step 4 (part of CSK_OJ_GAUGE_MAIN_JS).
Results:
Presto! We can see that the user can now interact with the gauge/input field in several ways:
- Directly with the input field (keyboard - numbers)
- Using the keyboard arrow keys to increment/decrement the value
- Using the mouse (or touch) to slide the gauge value
Demo of Quirks:
Why do we need cskOJKORefresh function in CSK_OJ_GAUGE_MAIN_JS?
This function is invoked every time the 'Send To Server' FieldChange event is triggered to take care of following data-binding issue after a server trip.
Why do we need to the addchg_%formname function invoked in the ViewModel?
After a server trip, if the
input field is not highlighted and if we try to use the
gauge to alter the value and send back to server, the change will not be propagated to the component buffer.
Reference Links:
Fluid UI - Oracle JET - Using Oracle Alta UI and Flex Layouts
Fluid UI - Oracle JET - Using KnockoutJS for Data Binding - Demo
PeopleTools 8.55+ - Using Oracle JET (JQuery, JQueryUI, requireJS and more):
Part 1,
Part 2,
Part 3,
Part 4