How to hack APEX Interactive Grid Part 3

If you haven’t read parts one and two yet you probably should before proceeding with this one. They covered some basics, configuration and toolbar and menu customization. In part 3 I’ll explain how to control and interact with Interactive Grid (IG) using JavaScript. As was already mentioned in parts 1 and 2 this is aimed at people with at least intermediate level experience with APEX and JavaScript Also most of the APIs are not documented or supported.

[Update 5.1.1 28-Mar-2017] This article has been updated to reflect patch release 5.1.1

Control

There are a few general ways to control and interact with IG from JavaScript code. One simple, common action that can be done to an IG is refresh the data. This is a documented and supported API.

apex.region("regionStaticID").refresh();

This same code will work to refresh any region that supports being refreshed (just supply the correct Static ID). This is the new official 5.1 way to refresh a region. There is also an equivalent dynamic action called Refresh (same as in previous releases but internally uses the apex.region API). A difference compared to other APEX components is that with IG the server returns just the data as JSON. Other components such as Interactive Reports return markup that includes more than just the data; for example the toolbar. This difference may only be of academic interest, but should not be a surprise once you understand the basic architecture of IG. Another differences is that if the IG is editable and has any changes then the user is prompted to confirm the refresh so that they don’t loose changes by accident.

If you don’t want to prompt the user you must explicitly clear the model changes first. The user should not be surprised about loosing changes. For example the following JavaScript code could be on a dynamic action on a button labeled “Cancel Changes”. (This is getting a bit ahead of ourselves by using a model API.)

[Update 5.1.1] The following code was updated for 5.1.1 to use getCurrentView method.

var ig$ = apex.region("emp").widget(),
    view = ig$.interactiveGrid("getCurrentView");

if ( view.internalIdentifier === "grid" ) { // only grid supports editing
    view.model.clearChanges();
}
apex.region("emp").refresh();

Another supported API on the region interface is focus. You can give focus to an IG with the following:

apex.region("regionStaticID").focus();

At this time there isn’t a corresponding DA action (Set Focus works for items but not regions).

Actions

The next easiest programmatic thing to do is invoke any of the menu or toolbar actions. In part 2 an example was given of defining an action and hooking it up to a toolbar button but little was said of what can be done with an action. (You should consult the doc comments in the libraries/apex/actions.js file for full details on the apex.actions API.) If you know the name of an action then you can run or execute the action with the invoke method. So the next logical question is “what are all the IG action names?” By now you probably know better than to ask where they are documented, right?

The following code typed into the browser console window of an APEX page with an IG on it will print out a nice list of action names along with the label and for radio group actions the choice value.

apex.region("emp").widget().interactiveGrid("getActions").list().forEach(function(a) { console.log("Action Label: " + a.label + ", Name: " + a.name + (a.choice !== undefined ? ", Choice: " + a.choice : "") ); });

You should be able to match the action name with what it does by the label which matches the toolbar button label or tooltip or menu item label. In the case of a toggle action the menu item label may not include the word Toggle. In the case of radio group actions the label may be on the tooltip or on a sub-menu label.

For example, the following code will open the IG Sort dialog just as if the user had clicked Actions menu, Data sub-menu and then Sort.

apex.region("emp").widget().interactiveGrid("getActions").invoke("show-sort-dialog");

The getActions method of the interactiveGrid widget returns the apex.actions context associated with the IG. Each IG has its own actions context. The action context is shared with all the sub widgets such as grid and recordView (Single Row View).

There are 3 kinds of actions. The most obvious is just known as an action. These are generally associated with a button or menu item. It has an action method which is a function that defines what it does when invoked. The above IG show-sort-dialog action is an example.

Toggle is another kind of action. These actions are generally associated with a checkbox, toggle button, toggle toolbar control, or toggle menu item. Rather than an action method it has get and set methods that set or get a Boolean value. The IG action edit is an example of a toggle action. To find out if the IG is currently in edit mode use this code:

apex.region("emp").widget().interactiveGrid("getActions").get("edit"); // returns true or false

To turn edit mode on:

apex.region("emp").widget().interactiveGrid("getActions").set("edit", true);

To turn edit mode off:

apex.region("emp").widget().interactiveGrid("getActions").set("edit", false);

The last kind of action is a radio group or choice action. It lets you select one value from a list of choices. These actions are generally associated with radio inputs, select lists, radio group menu items or radio group toolbar controls. These also have get and set methods. They also have an array of choices. The IG action change-view is an example of a radio group action. To find out what view is currently selected use this code:

apex.region("emp").widget().interactiveGrid("getActions").get("change-view");

To change the current view to chart view (assuming it is defined) use this code:

apex.region("emp").widget().interactiveGrid("getActions").set("change-view", "chart");

To find out the available choices use this code and look through the returned array:

apex.region("emp").widget().interactiveGrid("getActions").lookup("change-view").choices

Another example is saving the current grid. For this you can use the save action as follows:

apex.region("emp").widget().interactiveGrid("getActions").invoke("save");

This requires that the IG attribute Toolbar: Buttons Save is checked since it controls creation of both the button and the save action. You could use toolbar customization to remove just the Save button. Currently there is no easy reliable way to detect when the save has completed. [Update 5.1.1] If you need to do anything after the save is complete you can handle the save event. Events are covered in the next part of this series.

All the above information about actions applies to actions you create and add to the IG context as described in part 2. The examples in part 2 created actions to be invoked but you can also create toggle or radio group actions by implementing the set and get methods and for radio groups also defining the choices.

Widget Methods

If there isn’t a built-in IG action that does what you want there may be a way to accomplish it with JavaScript code calling methods on the various widgets that make up IG. Many of the methods on the interactive grid widget itself are not very stable in 5.1. [Update 5.1.1] We have already seen all many of the interactive grid widget methods that are useful right now. They are: getActions, getViews, getCurrentView and getCurrentViewId. [Update 5.1.1] Other IG widget methods are: resize, refresh, gotoCell, getToolbar, getSelectedRecords, setSelectedRecords, and focus. Refer to doc comments in the libraries/apex/widget.interactiveGrid.js source file for details on these.

Each of the different views (grid, chart, icon, and detail) are implemented by a widget. You can drill down into the view widget by first getting at the IG view interface. Using code such as the following:

apex.region("emp").widget().interactiveGrid("getViews", "grid");

Calling getViews with no argument returns an object containing all the currently defined views. Each property is the id of a view and the value is the view interface. So the following is equivalent to the previous statement as long as the view exists.

apex.region("emp").widget().interactiveGrid("getViews").grid;

You should make sure the view exists before trying to use it. You can use the getCurrentViewId to get the id (internalIdentifier) of the current view. [Update 5.1.1] You can use getCurrentView to get the current view. This is shorter than getting the current view id and passing it in to the getViews method.

The view interface has these useful properties:

  • view$ – this is the jQuery object of the view element.
  • model – this is the apex.model for the view.
  • internalIdentifier – this is the id of the view. For example “chart”
  • getSelectedRecords – this is a function that returns an array of the selected model records.
  • singleRowView$ – this is only defined for the grid view it is the jQuery object for the Single Row View element which is managed by the recordView widget.
  • rowActionMenu$ – [Update 5.1.1] this is only defined for the grid view. It is the jQuery object for the row actions menu.
  • selActionMenu$ – [Update 5.1.1] this is only defined for the grid view. It is the jQuery object for the selection actions menu.

An example using getViews, getCurrentViewId and the model property to clear changes in the model was given above.

The grid view has a number of useful methods. Consult the doc comments in the file libraries/apex/widget.grid.js for details. Here is a simple example. Suppose you wanted to select all the rows (as if the select all checkbox was checked). The following code would do that assuming the static id for the IG region is emp and the IG is configured to allow multiple selection and select all.

apex.region("emp").widget().interactiveGrid("getViews", "grid").view$.grid("selectAll")

The chart view uses the Oracle JET ojChart widget. You can consult the JET documentation for details (note the link may point to a newer version of JET than APEX uses). The following example will change the chart orientation to horizontal.

apex.region("emp").widget().interactiveGrid("getViews").chart.view$.ojChart("option", {orientation: "horizontal"})

This assumes the IG Static Id is emp, the current view is chart and the chart type supports the orientation property (for example it is a bar chart). Changes directly to the view generally do not affect the IG report settings.

That’s all there is to controlling the Interactive Grid region. The details are in learning about the available actions and widget methods. I’ve decided to add a forth part to this series to cover widget events and the data model layer; accessing, modifying, and listening to notifications.

10 thoughts on “How to hack APEX Interactive Grid Part 3

  1. Hi John,
    thanks for this post.
    I have a question may you can help me, is there a way to use the aggregation functions of the IG before the data are writen to db.
    I would like to sum up some colums, but the sum at the bottom should be updated when the cell has changed.

    Thanks for your help.

  2. In case anyone is wondering why the toolbar is not visible when you switch to a an Interactive Grid with Region Display Selector (it needs to be invisible on page load – either by setting RDC’s [Include ‘Show All’] to “No” or [Remember Last Selection] to “Yes”): it’s because its _create function hides all groups w/o visible children.
    Set Interactive Grid’s [Lazy Loading] attribute to “Yes” as a workaround.

  3. Hi John
    About APEX 5.1.
    Why is not Javascript editor in APEX linked to javascript library (
    …libraries\apex) to show the available methods and functions during typing the code.
    As example after typing:
    apex.region(“emp”).widget().interactiveGrid(”
    to see the methods.
    Thank you in advance for answer.

  4. I think it is a great post, if you can help doing the following,
    I need to populate the IG manually, I mean I have a list item in a master region and based on the selection I want to create the IG rows manually in a dynamic action, so adding rows, then filling the IG items. How could this be done please advise.

Comments are closed.