bvstone

Converting a Standard HTTP Form POST to jQuery .post() Method

Posted:

Converting a Standard HTTP Form POST to jQuery .post() Method

If you have been creating web applications over the years like I have, it seems like every day there are new features available to us, even if we're using RPG for our web application language.

One of my favorite tool sets, as you can tell by most of my articles, is jQuery.  

This example will show how you can use jQuery to update the method of POSTting (or even GETing) data.  We can take the "old" method of a simple form submission and very easily update it to use the jQuery .post() method.

For this example I chose to update a sample program that comes with the eRPG SDK.

If we go to the samples page for the eRPG SDK we see a sample program named Input2.  All this program does is read in data and then report it back to the screen using all of the different methods available to read and convert the input data.  The final program can be seen here.

First we display the HTML form:

<html>
<body>
<form action="/e-rpg/input2" method="post">
  Data: <input type="text" name="data">
  <input type="submit">
</form>
</body>
</html>

It's obvious from this HTML that when the use clicks the Submit button it will run program INPUT2.  This is a very simple program that reads in the data and writes that data back out using each of the available options for the #setDataCase() function within the eRPG SDK.  No, it's not free format.  It was written long before that was available (lol):

     H DFTACTGRP(*NO) BNDDIR('ERPGSDK')                                                             
      ****************************************************************                              
      * Prototypes                                                   *                              
      ****************************************************************                              
      /COPY QCOPYSRC,P.ERPGSDK                                                                      
      ****************************************************************                              
     D Data            S           1024                                                             
      ****************************************************************                              
     C                   callp     #startup                                                         
      *                                                                                             
     C                   callp     #loadTemplate('input2.erpg')                                     
     C                   eval      Data = #getData('data')                                          
     C                   callp     #replaceData('/%asis1%/':Data)                                   
      *                                                                                             
     C                   callp     #setDataCase(UPPER)                                              
     C                   eval      Data = #getData('data')                                          
     C                   callp     #replaceData('/%upper1%/':Data)                                  
      *                                                                                             
     C                   callp     #setDataCase(LOWER)                                              
     C                   eval      Data = #getData('data')                                          
     C                   callp     #replaceData('/%lower1%/':Data)                                  
      *                                                                                             
     C                   callp     #setDataCase(AS_IS)                                              
     C                   eval      Data = #getData('data')                                          
     C                   callp     #replaceData('/%asis2%/':Data)                                   
      *                                                                                             
     C                   eval      Data = #getData('data':1:UPPER)                                  
     C                   callp     #replaceData('/%upper2%/':Data)                                  
      *                                                                                             
     C                   eval      Data = #getData('data':1:LOWER)                                  
     C                   callp     #replaceData('/%lower2%/':Data)                                  
      *                                                                                             
     C                   eval      Data = #getData('data')                                          
     C                   callp     #replaceData('/%asis3%/':Data)                                   
      *                                                                                             
     C                   callp     #writeSection                                                    
     C                   callp     #cleanup                                                         
      *                                                                                             
     C                   eval      *INLR = *on     

The template used with this program is also very simple:

Content-type: text/html
Pragma: no-cache
Expires: Saturday, February 15, 1997 10:10:10 GMT

<html>
<body>
Data read in using #getData(variable).<br>
/%asis1%/
<br>
<br>
Data read in after using #setDataCase(UPPER).<br>
/%upper1%/
<br>
<br>
Data read in after using #setDataCase(LOWER).<br>
/%lower1%/
<br>
<br>
Data read in after using #setDataCase(AS_IS).<br>
/%asis2%/
<br>
<br>
Data read in after using #getData(variable:UPPER)<br>
/%upper2%/
<br>
<br>
Data read in after using #getData(variable:LOWER)<br>
/%lower2%/
<br>
<br>
Data read in using #getData(variable).<br>
/%asis3%/
</body>
</html>

This application works great and does what we want, but today users want things to be more interactive.  Moving from one screen to another just doesn't fit the flow of most modern applications today.

In order to update this application we will use jQuery and it's .post() method instead of doing a straight HTTP POST from the web form.  And the great thing is, we don't need to change our template or CGI program at all.  All we need to do is update the main page.  In this case we just copied the input2.html file to a new page named input3.html  The source of which follows:

<html>
  <body>
    <form action="/e-rpg/input2" id="showMeDataForm" method="post">
      Data: <input type="text" name="data">
     <button type="button" id="showMeDataButton">Submit</button>
    </form>
    <div id="showMeDataDiv"></div>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.66.0-2013.10.09/jquery.blockUI.min.js"></script>
    <script>
      $(document).ready(function(){
      
        $('#showMeDataButton').click(function(e) {
          	showMessage('Retrieving Data...');
            var formData = $('#showMeDataForm').serialize();
            var postURL = $('#showMeDataForm').attr('action');
            
            $.post(postURL, formData)
              .done(function(data) {
                $('#showMeDataDiv').html(data);
              })
              .fail(function(xhr, status, error) {
                $('#showMeDataDiv').html('There was an error!  See the console.');
                console.log('status' + status);
                console.log('error:' + error);
              })
              .always(function(data) {
                $.unblockUI();
              })
        });  
      
      });
      
      function showMessage(text) {
        $.blockUI({
          message:text,
          css: { 
                 border: 'none', 
                 padding: '15px', 
                 backgroundColor: '#000', 
                 '-webkit-border-radius': '10px', 
                 '-moz-border-radius': '10px', 
                 opacity: .5, 
                 color: '#fff' 
                }
        	});
      }
    </script>
  </body>
</html>

For this example I did choose to put all the JavaScript in the main page itself.  In real world applications I would move the JavaScript into it's own external file.  But, this way we have everything in one place to discuss how it works.

The first change we see is from the form itself.  

OLD:
    <form action="/e-rpg/input2" method="post">
      Data: <input type="text" name="data">
      <input type="submit">
    </form>

NEW:
    <form action="/e-rpg/input2" id="showMeDataForm" method="post">
      Data: <input type="text" name="data">
     <button type="button" id="showMeDataButton">Submit</button>
    </form>
    <div id="showMeDataDiv"></div>

Notice first we have given an ID to our form with the value of showMeDataForm.  

Next, we have replaced the submit button with an actual HTML button, also with an ID of showMeDataButton.  And finally we've added an empty DIV container named showMeDataDiv.  This is where the results of our POST will be placed.  This is instead of the old method of going to a completely different page.  (Please note, IDs when used with jQuery MUST BE UNIQUE on each element or they will NOT work.)

The next obvious update is the addition of a few <script> containers.

    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>

This first script container loads jQuery version 2.2.3 from Google's CDN, a Hosted Library of many popular JavaScript Libraries (and many thanks to Google for hosting these.. let's just hope they don't one day shut it down).  Using a CDN will allow your pages to load faster and save bandwidth for your network.  This is because the JavaScript library(ies) are loaded from an external source.

    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.66.0-2013.10.09/jquery.blockUI.min.js"></script>

This next script container loads a library known as BlockUI.  This is one library that isn't hosted by Google, but with most libraries like this you can normally find them out there somewhere.  What this library allows us to do is to show the user a status message when they click the submit button.   It also "blocks" the screen so that the user cannot click any buttons again, hence the name BlockUI.

    <script>
      $(document).ready(function(){
      
        $('#showMeDataButton').click(function(e) {
          	showMessage('Retrieving Data...');
            var formData = $('#showMeDataForm').serialize();
            var postURL = $('#showMeDataForm').attr('action');
            
            $.post(postURL, formData)
              .done(function(data) {
                $('#showMeDataDiv').html(data);
              })
              .fail(function(xhr, status, error) {
                $('#showMeDataDiv').html('There was an error!  See the console.');
                console.log('status' + status);
                console.log('error:' + error);
              })
              .always(function(data) {
                $.unblockUI();
              })
        });  
      
      });
      
      function showMessage(text) {
        $.blockUI({
          message:text,
          css: { 
                 border: 'none', 
                 padding: '15px', 
                 backgroundColor: '#000', 
                 '-webkit-border-radius': '10px', 
                 '-moz-border-radius': '10px', 
                 opacity: .5, 
                 color: '#fff' 
                }
        	});
      }
    </script>

Finally we have the main JavaScript code that does the interactive POST using jQuery's .post() method.

When using jQuery, normally we place most functions inside jQuery's document.ready() method block so that nothing will execute until the entire page is loaded.

Next we see we are assigning a function when the user clicks the button with the Id showMeDataButton.  We first serialize the form data using the serialize() method.  Put quite simply, this method "serializes" the form data, placing it in a name=value pair string just as we would expect data when doing a GET or POST (ie, field1=data1&field2=data2....)

Before making our post we will use the BlockUI function to display a message on the screen as well as block the UI on the page so the user can't click the button repeatedly (ya, this never happens... haha).  I have encapsulated the BlockUI function in the showMessage() function to make things more readable.  Normally in larger systems we will have many calls to BlockUI and this just makes things easier to read and use.

Next we use the attr() function to retrieve the "action" attribute from our form so that we know where to do our .post().

Finally, we call the .post() method.  This uses AJAX in the background to make the POST to our CGI program.  This is really the same as letting our form do the POST, except that all of the action is encapsulated inside the .post() function and we can do what we want with the returned results.

Another neat feature is that the .post() method allows the use of multiple callbacks for specific actions.  In our case we are using .done(), .fail(), and .always() callbacks which do exactly what we would expect.  .done() will be called when the the .post() completes normally .fail() is called if there is an error (normally resulting from a none 200 type status code from the .post()), and .always() will be called, well, always.    

When the .post() completes normally we use the .html() method to update the contents of our (what was empty) DIV container with the ID showMeDataDiv.

If we encounter a server error, the .fail() method is called and we update our showMeDataDiv with an error message and write the error details to the console using console.log() (which happens to be one of my favorite debugging tools.)

Finally, the .always() method will be called no matter what happens.  In this method we will "un-block" the display using the BlockUI method of .unblockUI().  This will return the page to it's previous state where the user can again interact with it.

So, as you can see, updating your CGI applications to be more interactive and user friendly doesn't have to be too difficult.  In fact, in most cases the CGI programs themselves won't need to change much, if at all.  Feel free to try out the application yourself by following this link.


Last edited 05/08/2017 at 10:07:00



Latest Posts:

QuickBooks Online - Subtotals and Discounts Frustration QuickBooks Online - Subtotals and Discounts Frustration
Posted by March 16, 2023
QuickBooks >> QuickBooks Online
Making the Switch From QuickBooks Desktop to QuickBooks Online - No Picnic Making the Switch From QuickBooks Desktop to QuickBooks Online - No Picnic
Posted by March 16, 2023
QuickBooks >> QuickBooks Online
BVSTools Software Verified on V7R5 and Power10 BVSTools Software Verified on V7R5 and Power10
Posted by December 9, 2022
BVSTools >> BVSTools Announcements
Microsoft Office 365 Servers and Random Errors Issue Microsoft Office 365 Servers and Random Errors Issue
Posted by November 14, 2022
BVSTools >> BVSTools Software Discussion >> Email Tools (MAILTOOL) Specific Discussion
Sending/Resending Emails Using a MIME File with MAILTOOL Sending/Resending Emails Using a MIME File with MAILTOOL
Posted by November 8, 2022
BVSTools >> BVSTools Software Discussion >> Email Tools (MAILTOOL) Specific Discussion
Sending an HTML Email on Your IBM i Using MAILTOOL Sending an HTML Email on Your IBM i Using MAILTOOL
Posted by November 1, 2022
BVSTools >> BVSTools Software Discussion >> Email Tools (MAILTOOL) Specific Discussion
Transferring License Keys from One System to Another Transferring License Keys from One System to Another
Posted by October 31, 2022
BVSTools >> BVSTools Software Discussion
Calculating the Size of a File Before Base64 Encoding Calculating the Size of a File Before Base64 Encoding
Posted by August 13, 2022
Programming >> RPG Programming
GreenTools for Microsoft Apps (G4MS) v9.12 Now Includes Function to Send Emails using MIME File GreenTools for Microsoft Apps (G4MS) v9.12 Now Includes Function to Send Emails using MIME File
Posted by August 11, 2022
BVSTools >> BVSTools Announcements >> GreenTools for Microsoft Apps (G4MS) Specific Announcements
GreenTools for Google Apps (G4G) v15.20 Now Supports Shortcuts GreenTools for Google Apps (G4G) v15.20 Now Supports Shortcuts
Posted by August 6, 2022
BVSTools >> BVSTools Announcements >> GreenTools for G Suite (Google Apps) (G4G) Specific Announcements
GreenTools for Microsoft Apps (G4MS) Groups Admin Authority Instructions GreenTools for Microsoft Apps (G4MS) Groups Admin Authority Instructions
Posted by July 26, 2022
BVSTools >> BVSTools Software Discussion >> GreenTools for Microsoft Apps (G4MS) Specific Discussion
GreenTools for Microsoft Apps (G4MS) v9.10 Now Includes OneDrive Functions that Work With Groups/Shared Drives GreenTools for Microsoft Apps (G4MS) v9.10 Now Includes OneDrive Functions that Work With Groups/Shared Drives
Posted by July 19, 2022
BVSTools >> BVSTools Announcements >> GreenTools for Microsoft Apps (G4MS) Specific Announcements
GreenTools for Google Apps (G4G) v15.10 Now Includes Drive Functions that Work With Shared Drives GreenTools for Google Apps (G4G) v15.10 Now Includes Drive Functions that Work With Shared Drives
Posted by July 15, 2022
BVSTools >> BVSTools Announcements >> GreenTools for G Suite (Google Apps) (G4G) Specific Announcements
GreenTools for Microsoft Apps (G4MS) v9.00 Now Offers Functions to Bypass Registration Command and BVSTools Landing Page GreenTools for Microsoft Apps (G4MS) v9.00 Now Offers Functions to Bypass Registration Command and BVSTools Landing Page
Posted by July 4, 2022
BVSTools >> BVSTools Announcements >> GreenTools for Microsoft Apps (G4MS) Specific Announcements
What Objects Should I Omit from Replication to Ensure My License Keys Work on my HA/DR System? What Objects Should I Omit from Replication to Ensure My License Keys Work on my HA/DR System?
Posted by June 27, 2022
BVSTools >> BVSTools Software Discussion

Reply




© Copyright 1983-2020 BVSTools
GreenBoard(v3) Powered by the eRPG SDK, MAILTOOL Plus!, GreenTools for Google Apps, jQuery, jQuery UI, BlockUI, CKEditor and running on the IBM i (AKA AS/400, iSeries, System i).