AJAX and Forms



 The good old HTML form element is used by many web pages for the

communication of the data from forms. This mechanism was developed to
work without any JavaScript or XML and long before AJAX.
It’s a typical scenario in web applications that they have some more or less
static forms with input fields for displaying and editing data values. Therefore
a concept to handle form situations is also needed in a AJAX engine.
This part is about the programming we need on the client. It’s implemented in
JavaScript and uses intensively XML documents. Some words about the
extensions in the Proxy Generator as well as the implementation on the server
will follow. Some samples can already be found on the samples WebSite.
Classical approach and drawbacks
The mechanism behind form element works since the beginnings of HTML to
send the data that is entered or changed by the user back to the WebServer.
The format used by these postings has nothing in common with XML but uses
for in many cases a URL like format defined by the mime type application/x-
www.form-urlencoded. With the upcoming XHTML 2.0 definition also a
XML Format and some more advanced form functionalities will be available.
But all these good news are not supported by the wide spread browsers
available today.
A direct access to the data inside a HTML Form in a whole does not exist in
the browser nor in JavaScript. But of course the individual elements can be
accessed one by one. The values that are shown to the user are normally
included inside the HTML code that is sent from the server to the client.
Collecting the values and sending them back to the server is hard coded to the
submit action of the form that normally downloads new HTML Code and
displays them in the window,
It’s obvious that this approach doesn’t fit into the processing of AJAX. The
graphical elements of the form and the data is not separated properly.
Using Form Data
One way to realize an access to the data in a HTML form for AJAX
applications is to use JavaScript. The include file ajaxForms.js was written to
enable the developer to handle this effectively and without using long scripts
in every form but to help with a collection of methods.
The goal of this approach is to distinguish between the data of the form
represented as a XML document and the HTML elements that are used to
display and edit the data.
To define a form on a HTML page you need a HTML Element that contains
all the form elements. This encapsulating element can be a DIV tag.
All the input fields, checkboxes, textareas and select objects with a name that
are inside this HTML element are considered holding data in the appropriate
object properties. This data is the assembled into a XML document with a
data root element by using the names of the HTML elements as the names of
the inner tags.
This HTML code ...
<div id="frm" style="margin: 2px; padding: 2px; border: solid 1px green">
<p>F1: <input name="F1" value="one by one"></p>
<p>F2: <input type="checkbox" name="F2"></p>
<p>T1: <textarea name="T1" style="width: 400px; height: 80px">some
text
lines</textarea>
<p>S1: <SELECT name="S1">
<option value="10">ten</option>
<option value="11">eleven</option>
<option value="12" selected="selected">twelve</option>
<option value="13">thirteen</option>
</SELECT>
</div>
... corresponds to this XML document:
<data>
<F1>one by one</F1>
<F2>false</F2>
<T1>some
text
lines</T1>
<S1>12</S1>
</data>
The data of a form is now available as a single value and therefore fits well
into the existing functionalities of the AJAX engine.
In AJAX applications it is a typical that the same HTML Form is reused
several times before getting and displaying new HTML code from the server
so we also need methods for the reverse data flow that puts the data of an
XML document back into the HTML form.
AJAX Form Services
The implementation of the AJAX Form Services, that allows an efficient
implementation of forms can be found in the JavaScript include file
ajaxForms.js.
Again, only one global object named ajaxForms is defined to minimize
possible name conflicts. Attached to this object the following methods are
available.
data = ajaxForms.getData(obj)
This method searches all INPUT, TEXTAREA and SELECT elements that
are contained inside the passed object and uses their values to build up the
elements of a XML document.
The obj parameter can be passed using the id of a formula or as a reference to
a HTML Object.
This result of this method is a XmlDocument object.
ajaxForms.setData(obj, data)
This method transfers all values from data into the corresponding INPUT,
TEXTAREA and SELECT elements of the HTML form. All HTML elements
that are part of the form but have no value in data will be cleared or
unchecked.
The obj parameter can be passed using the id of a formula or as a reference to
a HTML Object.
The data parameter can be passed as a XML text of a XmlDocument object.
This method also calls clearErrors at the end (see below).
ajaxForms.clearData(obj)
All HTML INPUT, TEXTAREA and SELECT elements that are part of the
form are cleared or unchecked.
The data parameter can be passed as a XML text of a XmlDocument object.
ajaxForms.resetData(obj)
All HTML INPUT, TEXTAREA and SELECT elements that are part of the
form get their initial value that is coded inside the
The obj parameter can be passed using the id of a formula or as a reference to
a HTML Object.
ajaxForms.processException(ex)
AjaxForms implements a mechanism to display exceptions that are thrown by
the server nearby the fields that causes them. If exceptions are handled by
ajaxForms.processException() all ArgumentException are detected.
To enable the developer how the exception text is shown SPAN elements
tagged with the css-class AJAXFORMEXCEPTION can be defined inside the
form. The text of the exception is then inserted into this Element and can be
formatted by using a CSS rule.
<span class="AJAXFORMEXCEPTION" name="LOANVALUE"></span>
ajaxForms.clearErrors()
This method clears all exception texts inside the form.
Sample for AJAX Forms
http://www.mathertel.de/AJAXEngine/S02_AJAXCoreSamples/KreditCalc.htm
This sample implements the processing of data of a form using the AJAX
engine and the AJAX Forms.
AJAX also brings some advantages to this kind of application on the
validation and calculation of formula data. Instead of "sending" the data and
retrieving new to be displayed HTML an asynchronous communication only
transfers the data part of the form using XML documents.
The supplementing functions necessary for the handling of AJAX Forms it is
necessary to include the ajaxforms.js scripts in the HEADER of the page.
<script type="text/javascript" src="ajaxForms.js"></script>
The connection to the corresponding WebService is done by using the proxy
generator:
<script type="text/javascript" src="GetJavaScriptProxy.aspx?service=_Kreditcalc.asmx"></script>
In this example the validation of the input values and the calculation of the
new values are together implemented in the same method. The
communication of the values between the client and the server uses the XML
format defined by ajaxForms.js module. The two functions ajaxForms.getData
and ajaxForms.setData that implement the transfer of the data from the XML
format to the HTML of objects therefore can be used directly in the setup of
the actions.
Exceptions
The function ajaxForms.processException can be used to handle and display
the exceptions that occur within validating the passed data.
If a wrong or missing value is detected inside the passed form data the server
should throw an ArgumentException using the name of the element as the
name of the wrong parameter.
This name is then passed to the client using an exception return package.
ProcessException then recognizes that an ArgumentException was thrown
and shows the error text beside the input field. To show these texts, a SPAN
element is used for each field inside the form:
<span class="AJAXFORMEXCEPTION" name="LOAN“></span>
The Form
The layout of the form and the data together with the format of the XML
document is specified by the HTML code of the page. The DIV element with
id frm (having a green border) is used as a container for all fields of the form.
Inside this object you can find the INPUT elements like:
<input id="loan" name="LOAN" value="100000">
...
<input name="MONTHLYREPAY" disabled="disabled">
The Actions
The first functionality on the server implements the calculation a simple credit
case. On the left side of the form some values like the loan amount and the
rates can be modified by the user. These values are used to calculate the
monthly payment, the duration of the credit and the totals of payment that are
displayed on the right side of the form.
For that purpose all the data of the form is send over the network to the server
as a XML document as well as the result of the calculation.
The first action uses the functions getData und setData from ajaxForms.js and
needs no further programming.
// declare an AJAX action
var action1 = {
delay: 200,
prepare: ajaxForms.getData,
call: proxies.KreditCalc.Calc,
finish: ajaxForms.setData,
onException: ajaxForms.processException
} // action1
The second implemented method on the server gets the same XML document
information as the first method but returns a XML Document containing the
monthly balance of the credit.
The code on the client is the responsible for displaying the chart by using the
special local implemented method displayAmortization. Here the XML
document passed back from the server is transformed into a HTML document
fragment by using a XSLT transformation on the client. This transformation
uses a lot of small blue and red images that are sized and positioned as needed
to make the chart look like it should.
Because the transformation is done on the client only about 23% of the
necessary HTML code is transferred over the network. The XSTL is retrieved
only once and is cached on the client.
var action2 = {
name: "Amortization",
delay: 800,
prepare: ajaxForms.getData,
call: proxies.KreditCalc.Amortization,
finish: displayAmortization,
onException: proxies.alertException
} // action2
Starting the actions
To start the asynchronous actions again the onkey event is used. In this
sample 2 actions are started by one event. Because both actions have a delay
time specified they will stay in the queue and will be removed and started
again when another key is pressed before the delay time is over.
The second parameter on starting the actions is used to reference the AJAX
form.
onkeyup="ajax.Start(action1, 'frm');ajax.Start(action2, 'frm')"
Use web services with multiple parameters in the AJAX
Engine
While it is possible to use web methods with multiple parameters when using
the web service proxies layer directly, the AJAX engine level is only
supporting one parameter - but there is a small trick that help you out of this
situation. Because the AJAX engine knows about all the asynchronous steps
that have to be done to complete the whole functionality of a complete AJAX
functionality it might make sense to use a WebService with more than a sinle
parameter.
You can find a sample that simply adds 2 integers at
http://www.mathertel.de/AJAXEngine/S02_AJAXCoreSamples/CalcAJAX.aspx
The prepare function is normally used for retrieving the client-side parameter
from the html objects. Because we need more than one parameter we just do
nothing here but returning the context object.
The call function, that is called next is not just pointing to the proxy function
of the method of the web service but needs some more code. It retrieves all
the parameters itself and then calls the proxy method WebService. The trick is
that the mechanism that handles asynchronous result messages is not hooked
up correctly and must be patched by using 2 lines of code for the regular and
the exception case:
proxies.CalcService.AddInteger.func = this.call.func;
proxies.CalcService.AddInteger.onException = this.call.onException;
Now the call will be processed asynchronously and the result value will be
passed to the finish function as usual.
Here the complete code that declares the AJAX action:
// declare an AJAX action
var action1 = {
delay: 200, // wait for multiple keystrokes from fast typing people
// the prepare function just returns the context object (if any)
// and makes it available to the call function.
prepare: function(obj) { return (obj); },
// the call is not pointing to the webservice proxy directly but calls it using several
parameters.
call: function (obj) {
var n1 = document.getElementById("n1").value;
var n2 = document.getElementById("n2").value;
proxies.CalcService.AddInteger.func = this.call.func; // patch
proxies.CalcService.AddInteger.onException = this.call.onException; // patch
proxies.CalcService.AddInteger(n1, n2); // and call
},
// the result will now be processed as usual.
finish: function (p) { document.getElementById("outputField").value = p; },
onException: proxies.alertException
} // action1

Post a Comment

You're welcome to share your ideas with us in comments.

Previous Post Next Post