Load, Validate, and Submit Forms using Ext JS 3.0: Part 3

Exclusive offer: get 50% off this eBook here
Ext JS 3.0 Cookbook

Ext JS 3.0 Cookbook — Save 50%

Clear step-by-step recipes for building impressive rich internet applications using the Ext JS JavaScript library

$29.99    $15.00
by Jorge Ramon | October 2009 | Cookbooks Open Source

Read Part One of Load, Validate, and Submit Forms using Ext JS 3.0.

Read Part Two of Load, Validate, and Submit Forms using Ext JS 3.0.

Loading form data from the server

An important part of working with forms is loading the data that a form will display. Here's how to create a sample contact form and populate it with data sent from the server.

Load, Validate, and Submit Forms using Ext JS 3.0: Part 3

How to do it...

  1. Declare the name and company panel:
      var nameAndCompany = { columnWidth: .5,
      layout: 'form',
      items: [
      { xtype: 'textfield',
      fieldLabel: 'First Name',
      name: 'firstName',
      anchor: '95%'
      },
      {
      xtype: 'textfield',
      fieldLabel: 'Last Name',
      name: 'lastName',
      anchor: '95%'
      },
      {
      xtype: 'textfield',
      fieldLabel: 'Company',
      name: 'company',
      anchor: '95%'
      },
      {
      xtype: 'textfield',
      fieldLabel: 'Title',
      name: 'title',
      anchor: '95%'
      }
      ]
      }

  2. Declare the picture box panel:
      var picBox = {
      columnWidth: .5,
      bodyStyle: 'padding:0px 0px 0px 40px',
      items: [
      { xtype: 'box',
      autoEl: { tag: 'div',
      style: 'padding-bottom:20px',
      html: '<img id="pic" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="' + Ext.BLANK_IMAGE_URL + '"
      class="img-contact" />'
      }
      },
      { xtype: 'button',
      text: 'Change Picture' }
      ]
      }
  3. Define the Internet panel:
      var internet = { columnWidth: .5,
      layout: 'form',
      items: [
      { xtype: 'fieldset',
      title: 'Internet',
      autoHeight: true,
      defaultType: 'textfield',
      items: [{
      fieldLabel: 'Email',
      name: 'email',
      vtype: 'email',
      anchor: '95%'
      },
      { fieldLabel: 'Web page',
      name: 'webPage',
      vtype: 'url',
      anchor: '95%'
      },
      { fieldLabel: 'IM',
      name: 'imAddress',
      anchor: '95%'
      }]
      }]
      }
  4. Declare the phone panel:
      var phones = { columnWidth: .5,
      layout: 'form',
      items: [{ xtype: 'fieldset',
      title: 'Phone Numbers',
      autoHeight: true,
      defaultType: 'textfield',
      items: [{
      fieldLabel: 'Home',
      name: 'homePhone',
      anchor: '95%'
      },
      {
      fieldLabel: 'Business',
      name: 'busPhone',
      anchor: '95%'
      },
      {
      fieldLabel: 'Mobile',
      name: 'mobPhone',
      anchor: '95%'
      },
      {
      fieldLabel: 'Fax',
      name: 'fax',
      anchor: '95%'
      }]
      }]
      }

  5. Define the business address panel:
      var busAddress = { columnWidth: .5,
      layout: 'form',
      labelAlign: 'top',
      defaultType: 'textarea',
      items: [{
      fieldLabel: 'Business',
      labelSeparator:'',
      name: 'bAddress',
      anchor: '95%'
      },
      {
      xtype: 'radio',
      boxLabel: 'Mailing Address',
      hideLabel: true,
      name: 'mailingAddress',
      value:'bAddress',
      id:'mailToBAddress'
      }]
      }

  6. Define the home address panel:
      var homeAddress = { columnWidth: .5,
      layout: 'form',
      labelAlign: 'top',
      defaultType: 'textarea',
      items: [{
      fieldLabel: 'Home',
      labelSeparator:'',
      name: 'hAddress',
      anchor: '95%'
      },
      {
      xtype: 'radio',
      boxLabel: 'Mailing Address',
      hideLabel: true,
      name: 'mailingAddress',
      value:'hAddress',
      id:'mailToHAddress'
      }]
      }
  7. Create the contact form:
      var contactForm = new Ext.FormPanel({
      frame: true,
      title: 'TODO: Load title dynamically',
      bodyStyle: 'padding:5px',
      width: 650,
      items: [{
      bodyStyle: {
      margin: '0px 0px 15px 0px'
      },
      items: [{
      layout: 'column',
      items: [nameAndCompany, picBox]
      }]
      },
      {
      items: [{
      layout: 'column',
      items: [phones, internet]
      }]
      },
      {
      xtype: 'fieldset',
      title: 'Addresses',
      autoHeight: true,
      hideBorders: true,
      layout: 'column',
      items: [busAddress, homeAddress]
      }],
      buttons: [{
      text: 'Save'
      },
      {
      text: 'Cancel'
      }]
      });
  8. Handle the form's actioncomplete event:
      contactForm.on({
      actioncomplete: function(form, action){
      if(action.type == 'load'){
      var contact = action.result.data;
      Ext.getCmp(contact.mailingAddress).setValue(true);
      contactForm.setTitle(contact.firstName + ' ' +
      contact.lastName);
      Ext.getDom('pic').src = contact.pic;
      }
      }
      });

  9. Render the form:
      contactForm.render(document.body);
  10. Finally, load the form:
      contactForm.getForm().load({ url: 'contact.php',
      params:{id:'contact1'},
      waitMsg: 'Loading'
      });


How it works...

The contact form's building sequence consists of defining each of the contained panels, and then defining a form panel that will serve as a host. The following screenshot shows the resulting form, with the placement of each of the panels pinpointed:

Load, Validate, and Submit Forms using Ext JS 3.0: Part 3

Moving on to how the form is populated, the JSON-encoded response to a request to provide form data has a structure similar to this:

{success:true,
data:{id:'1',firstName:'Jorge',lastName:'Ramon',
company:'MiamiCoder',title:'Mr',pic:'img/jorger.jpg',
email:'ramonj@miamicoder.net',webPage:'http://www.miamicoder.com',
imAddress:'',homePhone:'',busPhone:'555 555-5555',
mobPhone:'',fax:'',
bAddress:'123 Acme Rd #001nMiami, FL 33133',
hAddress:'',mailingAddress:'mailToBAddress'}}

The success property indicates whether the request has succeeded or not. If the request succeeds, success is accompanied by a data property, which contains the contact's information. Although some fields are automatically populated after a call to load(), the form's title, the contact's picture, and the mailing address radio button require further processing. This can be done in the handler for the actioncomplete event:

contactForm.on({
actioncomplete: function(form, action){
if(action.type == 'load'){}
}
});

As already mentioned, the contact's information arrives in the data property of the action's result:

var contact = action.result.data;

The default mailing address comes in the contact's mailingAddress property. Hence, the radio button for the default mailing address is set as shown in the following line of code:

Ext.getCmp(contact.mailingAddress).setValue(true);

The source for the contact's photo is the value of contact.pic:

Ext.getDom('pic').src = contact.pic;

And finally, the title of the form:

contactForm.setTitle(contact.firstName + ' ' + contact.lastName);

There's more...

Although this recipe's focus is on loading form data, you should also pay attention to the layout techniques used—multiple rows, multiple columns, fieldsets—that allow you to achieve rich and flexible user interfaces for your forms.

See Also...

  • The next recipe, Serving the XML data to a form, explains how to use a form to load the XML data sent from the server.
Ext JS 3.0 Cookbook Clear step-by-step recipes for building impressive rich internet applications using the Ext JS JavaScript library
Published: October 2009
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Serving the XML data to a form

XML is an information interchange format that can be used to provide the data that a form will display. This recipe shows how to create a contact form that feeds off the XML data that is sent from the server. This is how the contact form looks like after receiving the XML data:

Load, Validate, and Submit Forms using Ext JS 3.0: Part 3

How to do it...

  1. Build the name, company, picture box, internet, phone, business address, and home address panels as explained in the first six steps of the recipe Loading form data from the server.
  2. Create the contact form and assign it an XmlReader as its data reader:
      var contactForm = new Ext.FormPanel({
      frame: true,
      title: 'TODO: Load title dynamically',
      bodyStyle: 'padding:5px',
      width: 650,
      url: 'contact-xml.php',
      reader: new Ext.data.XmlReader({
      record: 'contact',
      success: '@success'
      },
      ['id', 'firstName', 'lastName', 'company', 'title',
      'pic','email', 'webPage', 'imAddress', 'homePhone',
      'busPhone','mobPhone', 'fax', 'bAddress', 'hAddress',
      'mailingAddress'
      ]),
      items: [{
      bodyStyle: {
      margin: '0px 0px 15px 0px'
      },
      items: [{
      layout: 'column',
      items: [nameAndCompany, picBox]
      }]
      },
      {
      items: [{
      layout: 'column',
      items: [phones, internet]
      }]
      },
      {
      xtype: 'fieldset',
      title: 'Addresses',
      autoHeight: true,
      hideBorders: true,
      layout: 'column',
      items: [busAddress, homeAddress]
      }],
      buttons: [{
      text: 'Save'
      },
      {
      text: 'Cancel'
      }]
      });

  3. Handle the form's actioncomplete event:
      contactForm.on({
      actioncomplete: function(form, action){
      if(action.type == 'load'){
      var contact = action.result.data;
      Ext.getCmp(contact.mailingAddress).setValue(true);
      contactForm.setTitle(contact.firstName + ' ' +
      contact.lastName);
      Ext.getDom('pic').src = contact.pic;
      }
      }
      });
  4. Render the form:
      contactForm.render(document.body);
  5. Finally, load the form:
      contactForm.getForm().load({ method:'get',
      params: { id: 'contact1' },
      waitMsg: 'Loading'
      });

How it works...

The contact form's building sequence is similar to the one described in the recipe Loading form data from the server. This is the resulting form, with the placement of each of the panels pinpointed:

Load, Validate, and Submit Forms using Ext JS 3.0: Part 3

Although a real-world application will most likely do some processing to generate the XML information, for this example the server page will generate sample data as simply as this:

<?php
header("content-type: text/xml");
echo "<?xml version="1.0" encoding="utf-8" ?>";
echo "<message success="true">";
echo " <contact>";
echo " <id>contact1</id>";
echo " <firstName>Jorge</firstName>";
echo " <lastName>Ramon</lastName>";
echo " <company>MiamiCoder</company>";
echo " <title>Mr</title>";
echo " <pic>img/jorger.jpg</pic>";
echo " <email>ramonj@miamicoder.com</email>";
echo " <webPage>http://www.miamicoder.com</webPage>";
echo " <imAddress></imAddress>";
echo " <homePhone></homePhone>";
echo " <busPhone>555 555-5555</busPhone>";
echo " <mobPhone></mobPhone>";
echo " <fax></fax>";
echo " <bAddress>123 Acme Rd #001 Miami, FL 33133</bAddress>";
echo " <hAddress></hAddress>";
echo " <mailingAddress>mailToBAddress</mailingAddress>";
echo " </contact>";
echo "</message>";
?>

The data consists of a message entity with a success attribute, which signals whether the request succeeded, and a contact entity for the contact information.

This data can be read by the form, thanks to the use of an XmlReader instance:

reader: new Ext.data.XmlReader({
record: 'contact',
success: '@success'
},
['id', 'firstName', 'lastName', 'company', 'title', 'pic','email',
'webPage', 'imAddress', 'homePhone', 'busPhone','mobPhone',
'fax', 'bAddress', 'hAddress', 'mailingAddress'
])

The handler for the actioncomplete event is used to process the results of the load or submit actions:

contactForm.on({
actioncomplete: function(form, action){
if(action.type == 'load'){
.
.
.
}
if(action.type == 'submit'){
.
.
.
}
}
});

When the handler processes the load action, it sets the default mailing address, the form's title, and the contact's picture.

As mentioned, the contact's information arrives in the data property of the action's result:

var contact = action.result.data;

The default mailing address comes in the contact's mailingAddress property, and the radio button for the default mailing address is set as shown in the following code:

Ext.getCmp(contact.mailingAddress).setValue(true);

The source for the contact's photo is the value of contact.pic:

Ext.getDom('pic').src = contact.pic;

And finally, the title of the form:

contactForm.setTitle(contact.firstName + ' ' + contact.lastName);

There's more...

XML is powerful and popular, and it is likely that you will encounter situations where it's appropriate to create forms that are able to read XML data. As you saw, this can be accomplished by using an XmlReader through the reader configuration option, instead of using the form's built-in support for processing JSON.

See also...

  • The previous recipe, Loading form data from the server, explains how to populate a form with data sent from the server

Using forms for file uploads

The Change Picture form is a great example of how to implement file uploads in your Ext JS application. This form is also a complement to the contact form examined in the Loading form data from the server and Serving XML data to a form recipes.

Load, Validate, and Submit Forms using Ext JS 3.0: Part 3

Let's see how it's done.

How to do it…

  1. Create the component that will display the contact's picture:
      var picBox = {
      columnWidth: '100 px',
      bodyStyle: 'padding:10px',
      items: [
      { xtype: 'box',
      autoEl: { tag: 'div',
      html: '<img id="pic" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="' + Ext.BLANK_IMAGE_URL + '"
      class="img-contact" />'
      }
      }
      ]
      }
  2. Create a panel with text boxes that show the file names for the current picture and the picture to be uploaded:
      var picFiles = {
      columnWidth: .65,
      layout: 'form',
      labelAlign:'top',
      items: [{
      xtype: 'textfield',
      fieldLabel: 'Current',
      labelSeparator: '',
      name: 'currPic',
      id:'currPic',
      readOnly: true,
      disabled:true,
      anchor:'100%'
      },
      {
      xtype: 'textfield',
      fieldLabel: 'New (JPG or PNG only)',
      labelSeparator: '',
      name: 'newPic',
      id:'newPic',
      style:'width: 300px',
      inputType: 'file',
      allowBlank: false
      }]
      }

  3. Define a custom validation function that will be used to validate that the file to upload is either a JPG or PNG file:
      function validateFileExtension(fileName) {
      var exp = /^.*.(jpg|JPG|png|PNG)$/;
      return exp.test(fileName);
      }

  4. Now, create the form and define a handler for the Upload Picture button:
      var pictUploadForm = new Ext.FormPanel({
      frame: true,
      title: 'Change Picture',
      bodyStyle: 'padding:5px',
      width: 420,
      layout: 'column',
      url: 'contact-picture.aspx',
      method: 'POST',
      fileUpload: true,
      items: [picBox, picFiles],
      buttons: [{
      text: 'Upload Picture',
      handler: function() {
      var theForm = pictUploadForm.getForm();
      if (!theForm.isValid()) {
      Ext.MessageBox.alert('Change Picture',
      'Please select a picture');
      return;
      }
      if (!validateFileExtension(Ext.getDom('newPic').value)) {
      Ext.MessageBox.alert('Change Picture',
      'Only JPG or PNG, please.');
      return;
      }
      theForm.submit({
      params: { act: 'setPicture', id: 'contact1' },
      waitMsg: 'Uploading picture'
      })
      }
      },
      {
      text: 'Cancel'
      }]
      });

  5. Define a handler for the actioncomplete event:
      pictUploadForm.on({
      actioncomplete: function(form, action) {
      if (action.type == 'load') {
      var pic = action.result.data;
      Ext.getDom('pic').src = pic.file;
      Ext.getCmp('currPic').setValue(pic.file);
      }
      if (action.type == 'submit') {
      var pic = action.result.data;
      Ext.getDom('pic').src = pic.file;
      Ext.getCmp('currPic').setValue(pic.file);
      Ext.getDom('newPic').value = '';
      }
      }
      });

  6. Render the form and load the existing picture for the contact:
      pictUploadForm.render(document.body);
      pictUploadForm.getForm().load({
      params: { act: 'getPicture',
      id: 'contact1'
      },
      waitMsg: 'Loading'
      });

How it works…

The component that will display the contact's picture is created first, followed by the text boxes that show the filenames for the current and new picture. To provide the ability to browse for the appropriate file, the new picture text box uses the inputType = 'file' config option, which creates the equivalent HTML element consisting of a text box and a Browse button.

A first layer of validation is provided by the validateFileExtensions function. This function uses a regular expression test in order to make sure the selected file has a PNG or JPG extension:

function validateFileExtension(fileName) {
var exp = /^.*.(jpg|JPG|png|PNG|txt|TXT)$/;
return (exp.test(fileName));
}

I recommend that you complement this function with server-side validation. This will guarantee that the uploaded file is actually a picture.

Carrying out the validation, as well as the submission, is the responsibility of the click handler for the Upload picture button. Notice the use of a request parameter (act: 'setPicture') to signal the server page that a new picture is being uploaded:

buttons: [{
text: 'Upload Picture',
handler: function() {
var theForm = pictUploadForm.getForm();
if (!theForm.isValid()) {
Ext.MessageBox.alert('Change Picture',
'Please select a picture');
return;
}
if (!validateFileExtension(Ext.getDom('newPic').value)) {
Ext.MessageBox.alert('Change Picture',
'Only JPG or PNG, please.');
return;
}
theForm.submit({
params: { act: 'setPicture', id: 'contact1'},
waitMsg: 'Uploading picture'
})
}
}

The actioncomplete handler is in charge of displaying the contact's picture. Upon a form load, the contact's current picture is displayed. After the form is submitted, the just-uploaded picture is shown:

if (action.type == 'load') {
var pic = action.result.data;
Ext.getDom('pic').src = pic.file;
Ext.getCmp('currPic').setValue(pic.file);
}
if (action.type == 'submit') {
var pic = action.result.data;
Ext.getDom('pic').src = pic.file;
Ext.getCmp('currPic').setValue(pic.file);
Ext.getDom('newPic').value = '';
}

Notice that after a successful upload, the JSON-encoded response will have the following structure:

"{success:true,data:{contactId:'contact id',file:'[picture path]'}}

There's more...

This approach is a good foundation for implementing file uploading code in Ext JS. You can easily modify it to accomplish multiple file uploads as well. More complex implementations are also possible through the use of plugins or extensions.

See also…

Building friendlier forms using text hints

Great usability is often attained with simple UI modifications. This recipe explains how you can make your forms easier to use by adding text hints to their contained fields. The next screenshot shows a form that contains text hints:

Load, Validate, and Submit Forms using Ext JS 3.0: Part 3

How to do it...

Create a form and use the emptyText configuration option to add text hints to the fields:

Ext.onReady(function() {
var commentForm = new Ext.FormPanel({
frame: true,
title: 'Send your comments',
bodyStyle: 'padding:5px',
width: 550,
layout: 'form',
items: [{
xtype: 'textfield',
fieldLabel: 'Name',
name: 'name',
anchor: '98%',
allowBlank:false,
emptyText:'Your name here'
},
{
xtype: 'textfield',
fieldLabel: 'Email',
name: 'email',
anchor: '98%',
vtype:'email'
},
{
xtype: 'textarea',
fieldLabel: 'Comments',
name: 'comments',
anchor: '98%',
height:200,
allowBlank: false,
emptyText: 'Enter your comments'
}],
buttons: [{
text: 'Send'
},
{
text: 'Cancel'
}]
});
commentForm.render(document.body);

There's more...

When using emptyText to specify the default text to place into an empty field, be aware that this value will be submitted to the server if the field is enabled and configured with a name.

See also...

  • The Specifying required fields in a form recipe, covered earlier in this article, explains how to make some form fields required
  • The recipe titled Setting the minimum and maximum length allowed for a field's value, covered earlier in this article, explains how to restrict the number of characters entered in a field
  • The Changing the location where validation errors are displayed recipe, covered earlier in this article, shows how to relocate a field's error icon

Summary

This article focused on forms processing. In this article you learned tips and techniques for effective field validation, details on how to load data into forms, as well as advice on how to use forms to upload files to the server. In this article you saw examples of how to extend the library's classes, in particular, how to create custom form fields.

[ 1| 2| 3 ]

If you have read this article you may be interested to view :

 

Ext JS 3.0 Cookbook Clear step-by-step recipes for building impressive rich internet applications using the Ext JS JavaScript library
Published: October 2009
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

About the Author :


Jorge Ramon is the Vice President of Development for Taladro Systems LLC, where he has led the design and development of a number of software products for the law industry—including QwikTime™ and LawDrill™.

Jorge has over 16 years of experience as a software developer and has also worked creating web applications, search engines, and automatic-control software. He actively contributes to the software development community through his blog: MiamiCoder.com.

Books From Packt

Moodle 1.9 Extension Development
Moodle 1.9 Extension Development

Moodle 1.9 Theme Design: Beginner's Guide
Moodle 1.9 Theme Design: Beginner's Guide

Moodle 1.9 for Design and Technology
Moodle 1.9 for Design and Technology

Moodle 2.0 First Look
Moodle 2.0 First Look

Joomla! 1.5: Beginner's Guide
Joomla! 1.5: Beginner's Guide

Joomla! 1.5 Multimedia
Joomla! 1.5 Multimedia

Mastering Joomla! 1.5 Extension and Framework Development (Update)
Mastering Joomla! 1.5 Extension and Framework Development

Hacking Vim: A Cookbook to get the Most out of the Latest Vim Editor
Hacking Vim: A Cookbook to get the Most out of the Latest Vim Editor

 

 

Your rating: None Average: 3.6 (5 votes)
nice by
Nice one it helps.
good one!! by
good one!!

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
u
8
F
C
s
b
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software