Enhance data entry with a Form Helper program

One of the more important developer features in Valence’s Nitro App Builder utility is the ability to easily wed back-end RPG business logic with front-end data entry forms in the web browser. This concept is most commonly put to work by adding a Save button to your app, then having its click action call a back-end RPG program to process entry fields in the app’s form widget(s). 

But prior to clicking Save, there is another mechanism you can utilize to enhance the user experience, leveraging the inherently dynamic nature of web browser applications. The process entails using a Form Helper RPG program to validate form fields as they’re changed, and to even dynamically alter UI elements based on selected or entered values. For example, you could have a “Country” drop-down field that, when changed, alters the contents of an adjacent “State” or “Province” drop-down field.

Let’s demonstrate how this is done by creating a very simple form that includes four basic fields for entering a Country, State, Province and City field, all of which are validated against a “ship to” file. Using the VXSHIP_TOS file included with Valence (version 6.2 and beyond), we’ll create separate data sources that will be used to populate the Country, State and Province fields as drop-downs, and we’ll set up the City as a standard text field. A Form Helper program will be created to control whether the State or Province drop-down show based on the selected Country, as well as updating the contents of the State or Province drop-down based on the Country.

So for our “Country” drop-down list, the data source SQL statement will look like this:

select distinct CNTRY_NAME, A3_CODE
from VXSHIP_TOS
inner join DEMOCNTRYS on A3_CODE=COUNTRY
order by CNTRY_NAME

Here we are joining DEMOCNTRYS to VXSHIP_TOS in order to spell out the abbreviated country name stored in the file. We will give this data source a name of SHIP_CNTRY.

Next we’ll create a data source for the State, putting the vvIn_virtual concept to use:

select distinct STATE
from VXSHIP_TOS
where COUNTRY = vvIn_virtual('selectedCountry', 'XXX', 'char', 3)
order by STATE

Here we are assuming an app variable called “selectedCountry” will be set to whatever country was selected in the Country drop-down. More on that in a moment. We will name this data source SHIP_STATE.

Next we’ll do a similar data source for provinces, saving it as SHIP_PROV:

select distinct PROVINCE
from VXSHIP_TOS
where COUNTRY = vvIn_virtual('selectedCountry', 'XXX', 'char', 3)
order by PROVINCE

So with our three data sources saved, we can move on to our hypothetical app that contains the form widget. This form, simplified for the purpose of this demonstration, is built over four fields from VXSHIP_TOS. Of course, for a “real” application you would likely pull the form fields from your own order header file. Our demonstration form widget looks like the following screenshot from the “Refine” tab in the NAB designer, using a “right” label alignment:

On the “Fields” tab note that the four fields have been marked as editable, and the first three field have been transformed into drop-downs, pulling from the three corresponding data sources we created earlier:

Finally, note the “Helper Program” button in the upper right of the “Fields” tab. This is where we designate the name of the RPG program we want this form widget to call as fields are changed. Click that button and you’ll see a configuration window like this:

Here we’re telling NAB to call our RPG program RPG1001 whenever the form is initially shown and whenever a field value in the form has changed, passing an action of “validateShipFields”. Form Helper programs should be modeled after example template EXNABFHLP, so you can start by making a copy of that source member located in VALENCE6/QRPGLESRC and calling it, in this case, RPG1001. Here’s what our RPG code will look like for this example:

Let’s walk through what this program is doing line-by-line:

  • (line 102) We are only concerned with calls to this program with an action of ‘validateShipFields’, as set in the Form Helper program configuration window
  • (104) pull in the COUNTRY drop-down field value (a three character code)
  • (105) If the call to this program occurred because the form is first being shown with new data, or the user made a change to the Country drop-down, we will do the following:
    • (106) set the app variable ‘selectedCountry’ to this value. This will be pulled in via the vvIn_virtual clause in the State and Province data sources we defined earlier
    • (108-111) if the user selected USA, we will hide the Province drop-down in the form, show the State drop-down, and refresh the drop-down (aka “Combo box”) based on the data source to which it is linked
    • (112-125) if any other country is selected, we will hide the State form, show and reload the Province form if there are any provinces set up for that country in our VXSHIP_TOS file
  • (127) If the call to this program occurred because the user made a change to the City text field, and at least 1000 milliseconds (1 second) has elapsed since their last keystroke, we will do the following:
    • (129) pull in the CITY value, upper casing it
    • (130-136) if there are no matching records in VXSHIP_TOS, mark the field as being in error. In this example we’re simply checking that the city is valid for the selected country, but you could of course take it a step further by checking it against the state or province as well.

When this program is compiled and the form widget is added into an app, it will look something like this when run (in this case, after “Canada” has been selected, thus hiding the State field and showing the Province field):

While we’re on this Form Helper topic, let’s take a moment to go through all the various checkbox configurations available in the Form Helper window for triggering a call to the RPG program:

  • Creation – Means the Form Helper RPG program will be called upon the very first instantiation of the form within the app. The global variable gMode will be set to ‘formRender’ when called.
  • Show – The program will be called whenever the form is shown, with gMode set to ‘formShow’. This can be useful for pulling initial values and adjusting other elements in the form accordingly.
  • Field Change – The program will be called whenever the value of a field has changed, even if the cursor is still inside the changed field (subject to the milliseconds of inactivity setting). The gMode variable will be set to ‘change’ in this case. Note that for drop-downs (combo boxes) the millisecond delay does not apply, as a ‘change’ call is made immediately after the user selects a value.
  • Field Blur – The program will be called whenever the user tabs out or clicks out of a field, regardless of whether the field has changed or not, with gMode set to ‘blur’.
  • Call even if form is in error – When checked, if a front-end validation throws the form into an error state (i.e., a field exceeds a maximum value, or an email address is not formatted properly), the Form Helper program will still be called whenever “Field Change” or “Field Blur” applies.

The recently introduced “Mask” setting can also be enabled on this screen to accommodate cases where a Form Helper program call may take some time to process, and you don’t want the user to click on anything or change any field values until the call is completed. When activated, the form will be masked and an optional “Please wait, system processing” type of message displayed until the call to the RPG program concludes.