IBM i EXTRA: Building Even More Dynamic Code
Blog
iCan

Categories

03/09/2011

Building Even More Dynamic Code

JavaScript eval lets us put RPG to use

By Aaron Bartell

There I was, minding my own business, when an idea hit me square between the eyes. I remembered that JavaScript had a special function named "eval" that allows you to dynamically invoke JavaScript statements at runtime. Why is this important and incredibly cool? Because it will help us move even more processing to the server and into RPG and out of the browser.

Let me explain. If we wanted to update an ExtJS text field, we’d usually do it with the following syntax:

Ext.getCmp('tfName').setValue('some new value')

In previous articles, we’ve taken this a step further by passing a JSON array with name-value-pairs declaring which components should have their values set (i.e., 'fldName': 'fldValue'). That was all fine, but I found I frequently needed to add new features and functionalities in both the client JavaScript and on the RPG server side of things. That’s when I realized we could eliminate changing the JavaScript side altogether by using the eval() function. Here’s how you’d accomplish the aforementioned setValue using eval:

eval("Ext.getCmp('tfName').setValue('some new value')");

Basically, all I’m doing is passing a string surrounded by double quotes into eval. Under the covers, eval will "compile" this code and immediately execute it. In theory, this means that ANYTHING we’re currently typing into our HTML document manually could be dynamically delivered from our RPG program to the client and executed.

Taking User Notifications Further

The idea came to me as I was looking for a friendly way to relay messages back to the user. My traditional approach was to use a small horizontal area at the top of the page to relay a message. Instead, I wanted something that had more eye appeal and features (i.e., a pop-up with rounded corners and would transition into and out of the page). After searching a bit in the Sencha.com forums I found an open-source ExtJS user extension named AlertBox. After playing around with the syntax of AlertBox, I was able to determine what would be necessary to make it work in conjunction with the JavaScript eval function so I could send a new AlertBox object from my RPG program to be dynamically displayed to the user. Because it used a lot of string concatenation, I created a separate service program named EXTJS with easy-to-call subprocedures to take care of all the dirty work, as shown in Figure 1. If you scroll down to the ExtJS_AlertBox subprocedure, you can see that I created parameters for the various configurable options the AlertBox allows. Note that a JSON pointer is passed in as the first parameter. This is necessary so we can subsequently add the JavaScript string to the global JSON response that will eventually be sent back to the client. You’ll notice that we aren’t actually invoking the json_* subprocedures here but instead are calling a more generic ExtJS_eval subprocedure to handle the process. ExtJS_eval was created to save on code duplication that other subprocedures in the same EXTJS service program, such as ExtJS_cmpShow, ExtJS_cmpHide and ExtJS_setValue, could also use.

Implementing the EXTJS Service Program

The next step is to implement those ExtJS_* RPG subprocedures into an actual program so we can see how they replace the traditional "uiactn" subprocedure approach I’ve taken in previous articles. For this purpose I’ve created RPG program EXTJSEVAL, as shown in Figure 2, that conveys both the use of ExtJS_* subprocedures and the previous approach that’s now commented out so you can use it for reference. For example, in subprocedure btnNxtPnl1 we see that extjs_cmpHide() has replaced the call to uiActn(). Also, in subprocedure btnNxtPnl2, you’ll see that extjs_cmpSetValue() replaced all of the various json_put* subprocedures. And lastly, you see btnStayPnl3 is still occupying gMsgTxt with an error message, and in subroutine endpgm we make a call to extjs_alertBox() instead of calling json_putString to send gMsgTxt back down to the user. That’s how the server side code changed with this new dynamic JavaScript eval approach. Let’s see how the client code changes.

Changing how we Process the Server Response

In Figure 3 we see the extjseval.html file, which contains all of the panel definitions we’re used to seeing. What’s different this time around can be found in the btnHandler JavaScript function toward the bottom of the source. The success config option of the Ext.Ajax.request object has our traditional call to JavaScript function uiActn() commented out and in its place is an Ext.iterate invocation that will loop through the JSON response and look for the evalList so it can process each subsequent eval name-value-pair. Figure 4 shows a screenshot of what the JSON response looks like when viewed in FireBug, along with the results of calling the window.console() API from within our JavaScript 'for' loop. I added the call to window.console() so you can see the exact command that’s being sent from the server and processed on the client. The key line of code in all of this is:

eval( uiCmpNam[uiActn] );

That will invoke the JavaScript statement as we saw earlier in this article where I had a hardcoded example.

That concludes the client-side coding. If you’re like me, your mind is swimming with other possibilities that could be accomplished with this newfound dynamic JavaScript statement processing. Let me share what I’m thinking. Imagine if we were to store the definition of an Ext.Panel in a DB2 table and instead of having any HTML files, we’d instead immediately invoke an RPG program. If that RPG program didn’t receive inbound parameters, it’d by default send back an Ext.Panel definition to be dynamically displayed in the browser. It’d be similar to doing something like this:

eval("new Ext.Panel({id:'pnlMain',..." );

Then when the user clicked a button in that panel, it’d communicate with the server again and we could send down another screen definition or some other actions to highlight a field that might have invalid data.

You Matter

Please continue to send me your ideas for future articles. I got an e-mail from an individual needing to create a dashboard with charts for mobile devices so they could prove to their C-level executives that RPG was still a major player in the modernization strategy. Stay tuned for an article on that as soon as SenchaTouch releases support for charts!


Aaron Bartell is an RPG and Java developer for www.krengeltech.com. Aaron can be reached at [email protected].


Figure 4


[back to article]