Saturday, September 10, 2016

Fluid UI - Using Oracle JET - UI Components - Visualizations - Status Meter Gauge

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

3 comments:

  1. Hi,

    I have used the function
    Declare Function SetConfirmationMessage PeopleCode PT_WORK.PT_CONFIRM_MSG FieldFormula;

    Local string &msg = MsgGetExplainText(2000, 138, "Data Saved SuccessFully.");
    SetConfirmationMessage(&msg);

    But it is reflecting only 2 times when i submit the data in fluid page, The 3rd time the message does not popup. can you please tell me how i can solve this problem?



    ReplyDelete
    Replies
    1. You may want to enable debugging (peoplecode/SQL trace) to determine why the code is not working the third time. Sorry for the delay in responding. I seemed to have missed this comment.

      Delete
  2. @Anonymous, what event are you triggering SetConfirmationMessage from? Are you sure the event is triggering?

    ReplyDelete