Enhance Your Grid Functionality with RPG

Traditionally, business systems of all stripes are loaded with all sorts of lists, whether it be in the form of subfiles in the legacy AS400 / i5 / iSeries world, or browser-based grids in the IBM i web world (a la Nitro App Builder in Valence). With so many users relying on the information conveyed through these lists, it’s imperative to make them as intuitive and user-friendly as possible.

Seasoned RPG programmers found myriad ways over the years to leverage 5250 display features in their subfile programs for maximum effect.  From changing colors, showing/hiding fields and controlling paging, developers could invoke all sorts of tricks to try to improve the user experience.

Likewise, NAB-based grids can also be manipulated from RPG, but with far less programming effort! This tip will review some of the more useful RPG interactions available to you.

For demonstration purposes, let’s take a look at a simple grid app built over the trusty DEMOCMAST file included with every Valence installation. This is a standard grid with a couple user filters in the toolbar:

Though you can add widget-level RPG helper programs for custom filtering and setting initial filter values, our main focus here is on app-level controls managed through linked app variables. These controls are accessed in the NAB Designer by opening the app containing the widget, then clicking on the “Link” icon that appears inside that widget:

This “Link” button will bring up a window containing multiple app variable settings through which an app-level RPG helper program, i.e. a program called through a Behaviors action, can send and/or receive instructions or values associated with the underlying grid widget.  In some cases you can bypass an RPG program call altogether and handle app variable adjustments in the front-end via Behaviors… 

As you can see, there are quite a few linked app variable options available for the grid here, so let’s take a quick walk through them all before we show a couple practical examples interacting with this DEMOCMAST grid.

Download controls:

(note: the visibility of these controls are dependent on the configuration of the underlying grid. For instance, PDF-related controls would only show if PDF downloads are turned on in the widget.)

  • csvFileName – allows you to override the file name of a downloaded CSV file (if CSV download is enabled). This can be handy for setting the file name based on a filter value (see “Get Filters” below for tips on retrieving filter values)
  • csvIncludeHeaders – if set to ‘true’ or ‘false’ this will override the “Include Headers” checkbox set at the widget level when CSV downloads are enabled
  • excelFileName – allows you to override the file name of a downloaded Excel file (if Excel download is enabled)
  • hideCsvDownload – if set to ‘true’ will remove the CSV download button from the grid (i.e., if the user should not be allowed to invoke the download)
  • hideExcelDownload – if set to ‘true’ will remove the Excel download button from the grid
  • pdfFileName – allows you to override the file name of the PDF file being downloaded
  • pdfFooter – sets or overrides the footer text on the PDF download
  • pdfHeader – sets or overrides the header text on the PDF download

Focus Filter controls:

  • On this tab you will see a list of column filters you’ve set up for the grid. By setting any one of these to ‘true’ you will make the cursor focus inside that field, thereby saving the user from having to click into a field that will likely require an entry.

General controls:

  • checkboxMulti – when the app variable assigned to this link is set to ‘true’ then a grid with checkboxes enabled will accept multiple selections; Likewise, setting this to ‘false’ will disable multiple selection functionality.
  • clearAllData – when set to ‘true’ all grid records are removed, as if no load has taken place.
  • data – this is an advanced function that can be used to override all the records shown in the grid. It must be a JSON array in the same format used by NAB to load the grid in the first place.
  • focusRow – when set to a numeric value, the grid will be focused (repositioned) to the corresponding row number (the first row being row 1)
  • focusRowRRN – when set to a numeric value, the grid will be focused (repositioned) to the corresponding relative record number of the primary file in the data source
  • nabHideWidget – when set to true, the grid widget will become hidden
  • nabShowWidget – when set to true, the formerly hidden grid widget will be shown
  • nabTotalCount – any app variable here will be automatically populated with the total number of rows in the grid
  • refresh – when set to ‘true’ triggers a reload of the grid
  • subTitle – when nonblank, assigns a subtitle to the grid. This can be used to indicate a common value for all rows (i.e., “Customer 123456 Open Orders”). The subtitle will appear in smaller text just below the main title.
  • title – assigns a main title to the grid

Get Filters:

  • On this tab you will see a list of column filters you’ve set up for the grid. By assigning app variables to these fields, you can retrieve the value the user has entered.

Hide Columns:

  • On this tab you will see a list of all the columns in the grid. An app variable associated to any of these columns will, when set to ‘true’, cause the column to become hidden.

Hide Filters:

  • On this tab you will see a list of column filters you’ve set up for the grid. An app variable associated to any of these columns will, when set to ‘true’, cause the filter to become hidden. This can be useful in cases where certain filters might not be appropriate to show based on the data being displayed.

Reload Filters:

  • Any filters that are linked to data sources (i.e., combo boxes) will be listed here. These filter values can be forced to reload by setting a linked app variable to ‘true’.

Reset Filters:

  • On this tab you will see a list of column filters you’ve set up for the grid. An app variable associated to any of these columns will, when set to ‘true’, cause the corresponding filter to be reset to its initial or default value.

Set Column Label:

  • On this tab you will see a list of all the columns and column containers in the grid. An app variable associated to any of these columns will, when changed, cause the column’s heading to be changed accordingly. This makes it possible to create custom column headings based on the data being listed.

Set Column Tooltip:

  • On this tab you will see a list of all the columns and column containers in the grid. An app variable associated to any of these columns will, when changed, cause the column’s tool tip to be changed accordingly.

Set Filters:

  • On this tab you will see a list of column filters you’ve set up for the grid. An app variable associated to any of these columns will, when its value is changed, cause the corresponding filter value to be changed accordingly.

Show Hidden Columns:

  • On this tab you will see a list of columns that are designated as Hidden.  When a designated app variable is set to ‘true’ then the corresponding column will become visible.

Summary Values:

  • Any columns that have summary functions (i.e., a total) will be listed in this tab.  When an app variable is assigned to any of these columns, that app variable’s value will be changed by NAB to the total value of that column.

So, with these linked app variable concepts for grid widgets defined, let’s go through a couple scenarios in which we could leverage the functionality in conjunction with an RPG program…

(1) Hide or show columns based on user ID

Let’s say you have a grid that needs to hide or show columns based on the job function of the user, which your RPG program can derive based on the logged in user ID. To achieve this you would want to assign app variables to the “Hide columns” and/or “Show hidden columns” linked app variables, depending on your situation. For our example here, let’s say that only users who work in accounting or sales should see the sales totals in the grid, so we’ll start by going into the App Variables list and adding a new app variable to control this called, intuitively, “hideSales”…

This app variable should in turn be assigned to control the visibility of the sales column, CYTDSALES, via the Hide Columns tab…

If we’re hiding the sales column in the grid, it would logically make sense to also hide the “Min sales” filter at the same time. This would be accommodated by applying the same “hideSales” app variable to the corresponding field in the Hide Filters tab…

Now that our “hideSales” app variable is being applied to the appropriate linked values, the last step would be to set up a simple RPG program that your app will call at startup. Here you can insert logic to determine if the user works in sales or accounting and, if not, hide the column and filter. The signal to the front-end is handled by simply setting the “hideSales” app variable to ‘true’:

Note that this program, which we’ve named INITVALS, is modeled after the EXNABSTART source member in QRPGLESRC. You would obviously have more robust logic for identifying sales and accounting users than using hard-coded user names, but you get the idea. Once the program is compiled, you must designate it as the startup program for your app via the right-edge slideout menu in Behaviors, where we also set the Action to trigger the conditioned section above:

The result of this will make the sales column and filter non-visible for non-sales/non-accounting users…

(2) Adjust the title based on specified filter values

Sometimes it can be helpful for context to adjust the grid widget title to indicate what it’s showing (or not showing) based on filter values or some other constraint in the underlying data source. In cases where the data source is straightforward and all filter values are showing in the toolbar above the grid, as is the case here, this title adjustment may not be necessary. But when you have extra filtering being applied, or the filters are being set inside a separate pop up window, it may be helpful to “remind” the user what constraints are being applied to the grid records. We can do this using a combination of a filter helper program and the linked app variables for setting the title and/or subtitle.

To start, we’ll create another app variable as explained in the first example above, only this time we’ll call it “titleOverride” and we’ll assign it to the “title” linked app variable under the General tab:

We can now save the app and move on to creating a filter helper RPG program modeled after EXNABFLT. This exit program will be called whenever the underlying grid widget is loaded, a concept that was described in another blog post several years ago, and will be updated for the forthcoming Valence 6.3 release soon. So let’s make a copy of EXNABFLT and call it FILTVALS, then insert some simple logic that will inspect the values of the two filters and adjust the “titleOverride” app variable accordingly (we’ll add the Action name to the exit program call settings in a moment)…

Finally, we’ll need to edit the grid widget (not the app) to tell it to call our filter exit program. This is specified in the Filters tab, inside the right-edge Settings slideout menu:

The end result of these changes will be a helpful title showing in the grid title whenever a filter is applied…