Monday, 28 January 2019

JET - display ADF BC entity validation messages

JET: v6.0.0
Source: GitHub

This is a quick and short article which talks about displaying ADF BC REST resource's validation message on the JET UI.

The inital step to is to create a validator method on one of the desired attributes of the ADF entity object. For my use case, I have selected Salary attribute on Employee EO.


While calling create or save on your collection data, the error callback has 3 parameters. The first parameter contains all the details of the error thrown. The responseText attribute shows the exact error text thrown from the REST end-point.


On encountering any error, the details are popped onto the UI. The messages are displayed via oj-messages component.


Cheers!

Monday, 21 January 2019

JET - master detail with ADF BC REST and pagination

JET: v6.0.0
Source: GitHub

Master detail view on the UI is something used often to showcase relational data. With Oracle JET, powered by ADF BC REST service, this becomes quite easy to achieve. However, it has to be mentioned that most of the hard work is done by the REST service. JET does not provide any out-of-box support for master-detail, you have to code a bit.

This article talks about a couple of approaches to this use-case. The first one is relatively faster, but works better on single child records. The second option is more robust as it handles multiple child records with pagination support.

To get started, we need to set the REST resource to support master-child relationship. The departments and employees are connected by a view link. The "departments" resource is updated to return child collection.



For the first approach, the department REST call is extended by an expand keyword. The expand keyword takes in the name of the child accessor, and this returns the child records in the response data. Without the expand parameter, only the master data is returned.


The JET model is updated to parse the EmployeesVO array from the response JSON.


When the department collection is built, the selection listener gets the current record and populates the ArrayTableDataSource observable with the EmployeesVO array. [Refer to my handling-table-selection-with-promise article for more details on extracting selection data].


The employees collection gets updated on department selection.


This approach is more suited when you want to display a single child record, as you get away with a single REST call to get your child record.

However, this approach has a downside! If your child accessor has many records, and you would want the power of JET's common model for pagination, this is not the way to go. Since this is one single REST call, the limit which is applied on the parent, is also applied on the child records. So if you have set 5 departments to be fetched at a time, it will also fetch 5 child employees (and not more!).

In order to achieve pagination support with common model, we need to create a URL of the following nature:

<ROOT>/departments/<SELECTED_DEPARTMENTID>/child/<ACCESSOR_NAME>?<OPTIONS>
For example: /departments/50/child/EmployeesVO?limit=5&totalResults=true


Create a new instance of Employee common collection with this URL and set it on the ojTable's CollectionTableDataSource object.



Cheers!

Monday, 14 January 2019

JET - programmatic UI validation

JET: 6.0.0, 3.2.0
Source: GitHub

The following article shows how to programmatically validate a set of JET UI components. For backward compatibility, the application has been extended to support the new JET 6.0.0 web components, as well as the older (on or before 3.2.0) html components.

The sample application consists of two forms, each of which has been built on a template supplied from the JS file. The validators and the button click functions have all been built through the underlying data structure.



The old style JET components are the ones using the html tags.

The modern web component structure is shown below:

The validation of the new web components is quite simple enough, as the custom components provide us with methods to validate them. The jQuery handle of these components has a tag name starting with OJ-. The validate and the showMessages methods have been used to check the components.


But for older JET components which made use of html tags, the validation is a bit different. The jQuery handlers provide us with methods with same names as the ojComponent type, and these methods perform the validation similar to above. Note the ojInputText("showMessages") and ojInputText("validate") methods below. Similar methods can be found for ojInputDate and other components.

Below example illustrates ojInputText and ojInputDate components.


The best way to find out about all the methods supported by a component is to list out the .__proto__ for the jQuery handle, or checking the JSDoc for the required component.

Validation has certainly become simpler with CCA components, but backward compatibility is also important!

Cheers!

Wednesday, 9 January 2019

JET - ojTable with custom date converters

JET: v6.0.0
Source: GitHub

This article talks about applying custom date and time patterns on the date columns of an ojTable component.

For those of you who are familiar with ADF, this is something similar to <af:convertDateTime> converter. Angular achieves similar functionality using pipes.

However, JET does not provide us with an out-of-the-box support for such conversions. We need to make use of oj IntlConverterUtils package.

After applying a conversion, this is the data structure we intend to achieve:



The inital data on the ojTable component looks like this, as fetched directly from an ADF BC REST API:


To achieve this conversion, I have used a template for the HireDate column, which passes the iso-string-date to a date-utils function.


The date-utils creates a converter with the passed pattern, and creates a new string. This is achieved using the following utilities from oj - oj.Validation.converterFactory and oj.IntlConverterUtils.dateToLocalIso methods.

The converter-factory creates a converter with the pattern passed from the template, intl-converter-utils uses this converter to generate a new string date.


You would need ojs/ojvalidation-datetime module in your define block.

Cheers!

Thursday, 3 January 2019

JET - ojModule custom configurations

JET: v6.0.0

The ojModule object provides us with some default configurations while creating a new application. These configurations help us to get started with the default folder structure or lifecycle hooks.

You can print the oj.ModuleBinding.defaults object in main.js file to see the complete list of configurable items.


If you need your own folder structure for your project, or if you want to have custom naming conventions for JET's lifecycle hook methods, this is the object you need to override.

For example, I have set the below configuration for my application:


This has allowed me to have the below folder structure:



And the below custom lifecycle hook methods:


Cheers!

Wednesday, 2 January 2019

JET - Handling table selection with Promise

JET: v6.0.0
Source: GitHub

This article explores a simple technique to get the selected data from an ojTable component. The click or selection event on an ojTable can be handled in multiple ways, and this concept can be extended to any event - onOjBeforeCurrentRow or onSelectionChanged.

Be it any of the above events, the data from the selection event on ojTable is of the same type. It consists of an array of objects, each of which has a startIndex and an endIndex. For a table supporting multiple selection, these values denote the index of the first selected row and the last selected row (respectively). For single selection, the start and end index is same. The selection object also consists of the Key attribute of the selected rows.

An interesting note: for multiple selection, when consecutive rows are selected - say row numbers 2 and 3 - the selection data generates a consolidated object, where start index is 2 and end index is 3. 


But, when we select random rows - say 0, 2 and 3 - the selection data event intelligently generates a consolidated array object - one with start index 0 and end index 0, and another with start index 2 and end index 3.


Using these start and end indices, we can locate the data at these indices inside the paging or array collection data source.

However, when we get the data at an index, using datasource.at, we get back a promise. If we have to loop through all the selected indices and get the data at each node, we would need resolve each individual promise. By the time we do this, the synchronous code will be completed and we will not have any way to handle the promise data.

The solution to this problem is to get all these promises in an array, and then resolve them all at once, using Promise.all.

I have a TableUtils js, which creates this array of promises.


This array of promises is handled all at once, and the data is extracted from the resulting array.



Cheers!