Showing posts with label JET. Show all posts
Showing posts with label JET. Show all posts

Wednesday, 25 March 2020

JET - show global processing icon

JET - v7.2.0
Source: GitHub

This is a quick demonstration on how to setup an application wide processing icon, which may be displayed every time a lengthy operation is in progress, and you don't want the user to perform anything else in the meantime.

JET provides a useful component - oj-progress - which may be used effectively for this purpose. This, along with some nice CSS tricks for creating an overlay, can solve our problem.

The oj-progress component is displayed on some boolean condition being set to true, and is hidden when the condition is set to false.

The component is placed at the root of the application, in index.html, so that it may be accessible to all child modules. The control is in appController.js, which is registered with the window object, so that the module may be accessed by any component, without the need to explicitly load it in the define block.


Tuesday, 17 March 2020

JET - with mongodb, nodejs and express

JET - v7.2.0

We all talk about the MEAN stack and the MERN stack. What about a MongoDB-Express-Nodejs-Jet stack this time? Can we call it the MENJ stack? I started on a POC and ended up on a full-blown cloud implementation of the stack. Sharing the POC results below.

Test users: refer to README.

Source code:
Oracle JET: (GitHub) hr-store
Node/Express: (GitHub) hr-server

The location/department/employee objects have been made similar to those from the HR schema, including the master child relationships. The master-detail page in the JET app implements this relationship.

Since I wrote my own middleware, I had the freedom of customizing the REST data to a standard easily suited to JET. However, I did have to extend the JET framework to support custom URL call and pagination.

This blog post may help you further to understand the master-child and search model implemented in this POC.

The front-end JET code has been deployed on heroku server. The Node/Express middleware is running on another heroku instance. You may access and play around with the deployed instance @

Disclaimer: since the front-end, middleware and database are all running in 3 different servers, the performance of the deployed instance is quite disappointing. But hopefully it will let you gain some amount of insight with the stack.


Wednesday, 16 October 2019

JET - using non-Oracle REST with common model

JET - v7.2.0
Source: {
  "front-end": jet-with-custom-rest,
  "server": test-server

We are so much used to building Oracle JET applications with ADF BC REST services. It is true that JET is developed quickest if you use an Oracle standard REST service (such as ADF BC). But it is also true that JET's common model architecture does support REST end-points which do not conform to Oracle standards.

Let's see an example. An Oracle standard REST sends response in the following format:

With these information available in the response, we assume that JET will take care of parsing the data and show a paginated table. This is true. If data, even if from a non-Oracle REST, is presented to JET in this format, we do not have to write any extra code to display the same on the UI.

But what if the data comes in this format (and that too from a POST request):

In this case, we have to extend some of the nice hooks provided by JET API to ensure that the new data format is understood by JET. Let's see how. For demonstration purposes, I am using a simple NodeJS express API.

The common model architecture uses two layers of data modelling - the oj.Model and the oj.Collection. The model represents a single row (or object), and is the blue-print of your data structure. The collection is simply an aggregate of models.

Both the model and the collection have a parse property each, which takes in a function. The collection's parse function takes in the entire raw response as a parameter. It is here that we would tell JET where to look for our data array. This is fired only once.

And in the parse function of the model, we get each item of the data array specified by the collection's parse method above, and it is here we tell model where to look for each row's attributes. This is fired for each item of the data array.

Now to support a custom POST end-point as the source of data, we need to set a function as a customURL for the collection. In this custom-url, we can set various options for the REST end-point that we intend to hit for data.

We're almost done. Before we wrap up, we use the total and pageSize values from the response into a customPagingOptions function.

For pagination, we need the total-count (totalResults) and page-size (limit). If offset is not available then it can be calculated from page as (page * pageSize). Or page may be calculated from offset as (offset / pageSize). It all depends on what parameter is understood by the REST from which we are fetching data. In my case, I am sending the page value.

We are all set up. Run ojet serve and we get this:


Monday, 12 August 2019

JET - router defaults and parameters

JET - v7.1.0
Source: GitHub

This is a quick tip on Oracle JET Router configurations. There are a couple of ways through which we can pass parameters while navigating using ojet Router.

1) You can set some global parameters while setting up the router configuration. This parameter is available on the static Router.rootInstance object.

This value can be accessed via the Router's rootInstance's current-state.

Using this value I can set the default tab whenever I enter a module.

2) The second option is to set a dynamic value while programmatically navigating to a module using ojet router. We use the store() method to set a parameter, and the retrieve() method to fetch it. The router param gets written to the URL to let you have a bookmark.

We can make use of this method to set a user-defined value as the default tab when we navigate across different modules.

Remember: there is only one instance of jet router for the application. So when you exit the module, you can make use of the handleDeactivated life-cycle hook and pass an empty object to reset the parameter, so that the parameter is no more available to other modules.

** Refer to the router-tab and playground modules in the GitHub source code.


Tuesday, 30 July 2019

JET - CCA communication with writeback

JET: v6.0.0
Source: GitHub

I found a nice YouTube video (Inter-module Communication with Custom Events) by John Brock, on the topic of inter-module communication in Oracle JET, using the concept of event bubbling.

The above method proposed by John will certainly solve communication problems between two JET modules, between a JET module and a CCA and also between two CCAs, and is thus a highly useful one.

However, there is another quick method to establish connectivity between two JET web components (CCAs), and that is through the writeback feature. This is essentially a quick solution, and works only between CCAs in one page (or module).

The writeback feature essentially means that when a property of a CCA is changed, the changed value is communicated to the component which is hosting the CCA. A crude and high-level process diagram would be something like this:

The app-controller contains an observable, which is a writeback-enabled property of CCA1. When this property is updated on the CCA, the value is also updated on app-controller. The subscription handler of this observable updates a variable on CCA2. The same flow is applied from CCA2 to CCA1.

The above example shows two CCAs placed on the index page of the application. When something is updated on the textbox of CCA1, the same message is displayed in CCA2, and vice versa.


Thursday, 23 May 2019

JET - create and register custom converter

JET: v6.0.0
Source: GitHub

This article speaks on simplifying the process of creating and registering a custom converter in your Oracle JET application.

The entire job can be essentially broken down into 3 parts:
1. Creating the custom converter (including the logic for formatting the input data).
2. Registering the new converter with JET runtime, and finally,
3. Using the converter.

The converter which I am going to talk about is a Phone-Number-Converter. It takes in a string or a number input value, and changes the same into (###) ###-#### format. Just to keep it simple, it assumes that a phone number should always be of 10 digits.

The entire logic for the new converter is in an external file - PhoneNumberConverter.js. The converter's format method takes care of the logic for the conversion.

Next, we need a factory method (IIFE) to create an instance of this converter, as soon as it is invoked.

Finally, the converter is registered with JET runtime validation library.

Now we are all set to use this "phonenumber" converter in our code.


Monday, 22 April 2019

JET - fetch all rows from ADF BC REST service

JET: 6.0.0
Source: GitHub

Oracle JET and ADF BC REST have a fantastic work relation. Each power-house seems to complement the other. As an example, JET's pagination module handles the entire responsibility of breaking up the data into chunks and fetches them as necessary, as and when the user navigates through the pages. The developer just needs to specify the page-size, and the framework divides the entire row-count into chunks of page-size, and uses the offset value to incrementally fetch the newer sets of data.

However, there might be times, when you need the entire data-set inside your JS array, without having the luxury of any pagination to do the job incrementally for you. In such cases, the below technique might help.

Step 1: Fire a rest call with totalResults=true, to fetch the total row count of your rest query.

Step 2: Use this row count value, and divide it into multiple chunks. E.g., I have decided to fetch 50 records at a time. Hence, the offset values would be 0, 50, 100. Each URL is sent to our helper method, which returns a promise.

You may set the limit value as a configurable option

Offset 0 fetches rows 1 to 50, offset 50 fetches 51 to 100, offset 100 fetches 101 to 107.

Step 3: I now have an array of promises, which I can evaluate all at once.

And there you go. You have the entire data set at your disposal. You may further optimise this process as per your need.

If you are familiar with ADF business components, a similar technique is used there as well. The developers configure the fetch-size for the view objects. The ADF framework gets a hold of the total row count, and then uses these information to decide on the number of database server trips and fetch the required number of rows per trip.

In the end, there are a few points quite worth mentioning:
1. A very high limit value may serve your purpose, but that is just a random guess, and did not seem very efficient to me.
2. This is just a technique to showcase an interesting use of totalResults and offset features of ADF BC REST. Large data sets should always be handled through a pagination or load-more-on-scroll mode. Not only are they performance boosters, they are also helpful from the UX perspective. So unless you really need to work on the entire data set at once (for displaying a chart maybe), this is not recommended.


Thursday, 4 April 2019

JET - ojChart context menu

JET: 6.0.0
Source: GitHub

Sometime back I had written an article - JET - custom event wrappers -  on how to add some custom information to an event raised by a component and then throw the event wrapped under your own custom event.

This article is just an extension of the same thought, which demonstrates how effectively you may use the above concept to solve your problem.

Here is the use-case:
We have an oj-chart component, which has a context-menu. Depending on the bar or pie slice which fired the context menu, we need to capture the chart data and act accordingly when the user clicks on any of the menu options.

However, the action event (on-oj-action) from oj-menu does not capture any information regarding the chart series or group.

But, oj-menu has a beforeOpen event (on-oj-before-open), which fires just before the context menu pops up and, more importantly, which captures all the data that we need.

So how do we make use of this event to solve our problem?

Step 1: Context menu fires beforeOpen event. We get chart related data from this event.
Step 2: We store the chart data in a variable.
Step 3: Context menu option click fires action event. This event is captured, the extra information is attached from the variable in step 2, and thrown again as a custom event.

This custom event now has all the data from the chart, which was captured from a different event. All we did was to combine the data from the two events.

Step 1

Step 2

Step 3

When the user finally clicks on one of the options in the context menu, we see that the chart details have now been captured in the detail part of the custom event, which were not present in the native event.


Tuesday, 2 April 2019

JET - dynamic content with templates

JET: v6.0.0
Source: GitHub

Oracle JET gives us developers a powerful tool - knockout templates - through which we can configure an entire page, using just JavaScript object metdata. The most significant advantages of such a mechanism are re-usability and of course, ease of development.

Imagine I would like to create the below 3 forms:

To make life of developers easier, all I would want them to do is to pass the metadata (fancy name for a JavaScript object), which would contain all the information about the fields, and not worry about the UI at all. This would also ensure a consistent look and feel for the entire application.

So let's see how such a template works. Each template has a declaration section and a definition section.

In the template declaration, I would specify where in my HTML page would I want the template code to be placed.

Template declaration

The template definition defines the exact implementation of the HTML code. It makes use of the metadata to position the HTML elements, which ultimately gives shape to the UI.

Template definition

To make it a bit easier, I have wrapped up the template inside a custom component, to make repitition simpler. This is the metadata I am passing to the template in order to get the desired structure:

Custom component


Monday, 18 February 2019

JET - custom event wrappers

JET - v6.0.0
Source: GitHub

Since the introduction of web components (formerly known as CCAs) in Oracle JET, the HTML development pattern has become quite standardized for a developer. Almost all the UI components provided by JET development team have now been converted into custom elements, with their own set of properties, methods, events, etc.

However, there are times when your business use-case may not be sufficiently fulfilled by the components provided by default, and you may need to stretch them. One such recent use case was to return some extra information from an event raised by a JET custom element.

To demonstrate this use-case, I would use an oj-chart and its corresponding oj-drill event. When drilling is on, the on-oj-drill event handler provides us with an event object, whose detail section gives us all the information about the selected bar or pie section.

To solve the problem of adding extra information to the event, we wrapped up oj-chart inside our own web component, and added a wrapper around the on-oj-drill event to throw our own event.

The original element - oj-chart - throws a on-oj-drill event when the pie slice is clicked. The wrapper web component - hr-chart -  intercepts this event, adds some extra information, and throws a new CustomEvent - on-drill-down.

When the custom wrapper event is printed on the console, we see the desired custom information, along with the original information passed on by the JET element.

A more practical example of this feature has been explained in this blog.