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:

GreenTools for G Suite (G4G) Now Includes Send Mail Functionality (G4GSMAIL Addon) GreenTools for G Suite (G4G) Now Includes Send Mail Functionality (G4GSMAIL Addon)
Posted by August 27, 2019
BVSTools >> BVSTools Announcements >> GreenTools for G Suite (Google Apps) (G4G) Specific Announcements
GreenTools For G Suite (G4G) v12.00 Released With Base OAuth 2.0 Functionality GreenTools For G Suite (G4G) v12.00 Released With Base OAuth 2.0 Functionality
Posted by July 28, 2019
BVSTools >> BVSTools Announcements >> GreenTools for G Suite (Google Apps) (G4G) Specific Announcements
BVSTools Small Price Increase in 2020 BVSTools Small Price Increase in 2020
Posted by July 26, 2019
BVSTools >> BVSTools Announcements
GreenTools for Vertex Cloud (VTXCLOUD) Now Available GreenTools for Vertex Cloud (VTXCLOUD) Now Available
Posted by July 22, 2019
BVSTools >> BVSTools Announcements >> GreenTools for Vertex Cloud (VTXCLOUD) Specific Announcements
GreenTools for Google Apps (G4G) - Drive Addon Successfully Verified by Google GreenTools for Google Apps (G4G) - Drive Addon Successfully Verified by Google
Posted by July 22, 2019
BVSTools >> BVSTools Announcements >> GreenTools for G Suite (Google Apps) (G4G) Specific Announcements
Why I Cancelled my DynDNS Service and How I Replaced It with an IBM i Application Why I Cancelled my DynDNS Service and How I Replaced It with an IBM i Application
Posted by July 17, 2019
IBM Power Systems >> (QGPL) IBM i
Green Tools for G Suite (G4G) Product Updates (Licensing, Functionality, Base Product) Green Tools for G Suite (G4G) Product Updates (Licensing, Functionality, Base Product)
Posted by July 13, 2019
BVSTools >> BVSTools Announcements >> GreenTools for G Suite (Google Apps) (G4G) Specific Announcements
Reading JSON Data from Standard Input With YAJL and RPG Reading JSON Data from Standard Input With YAJL and RPG
Posted by July 12, 2019
Programming >> Proof of Concept (POC)
MAILTOOL Updated to Allow Use of IBM Global Security Kit (GSKIT) for SSL/TLS Communications MAILTOOL Updated to Allow Use of IBM Global Security Kit (GSKIT) for SSL/TLS Communications
Posted by June 19, 2019
BVSTools >> BVSTools Announcements >> eMail Tool (MAILTOOL) Specific Announcements
GETURI v10.00 Released Supporting IBM Global Security Kit (GSKIT) and Server Name Indication (SNI) GETURI v10.00 Released Supporting IBM Global Security Kit (GSKIT) and Server Name Indication (SNI)
Posted by June 11, 2019
BVSTools >> BVSTools Announcements >> Get URI (GETURI) Specific Announcements
BVSTools Now Offers Vertex Cloud Interface BVSTools Now Offers Vertex Cloud Interface
Posted by April 15, 2019
BVSTools >> BVSTools Announcements
Token Has an Invalid Signature Error for Office 365 Email Token Has an Invalid Signature Error for Office 365 Email
Posted by March 22, 2019
BVSTools >> BVSTools Software Discussion >> GreenTools for Microsoft Apps (G4MS) Specific Discussion
Resending Emails that have Errored Out with Updated Router or Authentication Information Resending Emails that have Errored Out with Updated Router or Authentication Information
Posted by March 1, 2019
BVSTools >> BVSTools Software Discussion >> Email Tools (MAILTOOL) Specific Discussion
BVSTools Offers Toolset to Work With HubSpot OAuth 2.0 APIs On Your IBM i BVSTools Offers Toolset to Work With HubSpot OAuth 2.0 APIs On Your IBM i
Posted by January 27, 2019
BVSTools >> BVSTools Announcements
G4MSDRV Currently Not Supported G4MSDRV Currently Not Supported
Posted by January 17, 2019
BVSTools >> BVSTools Announcements >> GreenTools for Microsoft Apps (G4MS) Specific Announcements

Reply




Copyright 1983-2019 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).