To err is human to forgive is good programming, a look at error handling and extjs 4 forms

Displaying error messages in Extjs is not a terribly difficult task once you get the hang of the syntax and standardize all of your try / catch backend code. This post will present various ways to handle errors that may happen in your application so that you may provide users with a more meaningful message, and in turn help save some time when debugging. This is in fact an enhanced version of the Ext form example, and dives into areas where the example leaves off, the actual form is posted below so go ahead have a try, and look at the code if you would like before reading the explanation below. Once you download Ext you should have a folder called /examples/ in that folder you should have another folder called /form/ and finally in that folder open the file contact-form.js (here’s the link in case you have not downloaded the extjs library yet).

These examples are great but they all leave out one thing, data interaction between the form and the ‘back end’ of your web application. The block of code between lines 82 – 90 spell it out, and this will be the block that we modify to present us with a dummy response from the server.

  handler: function() {
         if (this.up('form').getForm().isValid()) {
              // In a real application, this would submit the form to the configured url
              // this.up('form').getForm().submit();
              this.up('form').getForm().reset();
                            this.up('window').hide();
                            Ext.MessageBox.alert('Thank you!', 'Your inquiry has been sent. We will respond as soon as possible.');
                        }
                    }

Since the code is written in extjs4 some of the syntax is new, for example, this.up(‘form’).getForm().isValid() looks a little different than the familiar Ext.getCmp(‘id’).getForm().isValid(), and you are free to use either one, the up abstract component walks up the ownerCt axis and returns the ancestor container with the parameter as the simple selector, in this instance the ‘form’ selector returns the form container. If we had specified an id in the form we could have used the following code to achieve the same result, Ext.getCmp(‘the_form’).getForm().isValid(). It pays to take a look at the abstract components and understand where and when you can use them, a full list can be found here in the Sencha documentation: http://docs.sencha.com/ext-js/4-0/#/api/Ext.AbstractComponent.

Error handling takes place in two areas in a web application, first, at the client side, which is the local browser, and finally, at the server side, which means that the data has been passed to the server and you are validating it then passing the results of the validation back to the client side browser. As a general rule you will want to do as much validation as possible at the client side before you send the code over to the server, this will save you in processing time and will speed up your applications, as well as prevent potential security threats to enter your server via your web forms.

The Client Side

In extjs 4 Sencha has made it easier to add on custom alert boxes when the client side validation fails. I know the underlined form elements clad in wavy red squiggles should be an indication that you have left something out or done something wrong, however, in the real world where your application is bound to wind up there are users who overlook this subtle hint. A modal dialog box clearly stating the obvious can be achieved using the code below.

Before:
We wrapped the form submit with the following if statement, preventing submission if the client side validation failed.

if (this.up('form').getForm().isValid()) {
	…
// Our form submit stuff
}

Now, we have the built in failureType property for the form action we can omit the if … then statement above and just insert the following code in out failure function of the form handler.

After:

  if (action.failureType === Ext.form.action.Action.CLIENT_INVALID) {                      
  Ext.Msg.show({  	
    title:'Error',												
    msg: 'Please complete the fields that are outlined in red.,						
    icon: Ext.Msg.ERROR,
    buttons: Ext.Msg.OK
		 });       
 }

This will abort the form submission, and give the user a nice visual warning in the form a of an error message that they will have to click on before correcting their form data.

The Server Side – Timeouts and other server side errors (non-application driven)

A great improvement over earlier versions of extjs is the fact that there is now a built in way to handle timeouts and server side errors so that your code is not left in a suspended state. Just as the client side example above, we will insert a if .. then block in the failure function of the handler, this time concentrating on the failureType Ext.form.action.Action.CONNECT_FAILURE.

if (action.failureType === Ext.form.action.Action.CONNECT_FAILURE) {                      
     Ext.Msg.alert('Error', 'Status:'+action.response.status+': '+   action.response.statusText);    
 }  

The result is below where 404 is the server side status and Not Found is the response text, this could be 503 Out of Resources, 500 Server Error, and the list goes on. (http://www.html-faq.com/serverbasics/?http )

Server Side validation

Ok there will be times when you absolutely have to validate data on the server side, be it a lookup against another table, an elaborate cross reference, whatever the reason, you will have to do it. The JSON below will indicate that there has been a server side failure.

       {success: false}	

You could stop with the simple statement above and give the user a generic error message, but since you are taking the time to read this far you are probably not that type of programmer and you want to give the user a little more information. In the example code we have the following fields, firstName, middleInitial, lastName, emailAddress, subjectField, and messageField. We can assume that any of these fields could hold invalid data, and there could be an infinite number of reasons why, now the task is to get the fields to the front end or client side and give the user a reason why the data was not acceptable. The JSON that you will have to return from the server to accomplish this consists of two parts, first, success must equal false, and second you should follow that with an object where the field name or id is followed by the error message that you would like to display, an example for the lastName field in our example form is below.

{    success: false,  errors: {  lastName: "Client not found" }}

The final piece is to put the code in place in the failure function of the action handler that will show the user the fields and messages you passed back with the JSON above. The code to do this is below.

if (action.failureType === Ext.form.action.Action.SERVER_INVALID){                         
	 // server responded with success = false
	form.markInvalid(action.result.errors);     
  }	

You should see something like this.

I have attached the source code to the modified example that you find in its entirety here … The only things you have to remember is that if you would like to turn off the client side validation you must do so by setting the clientValidation property to false, and that you can get pretty specific with the client side validation by using the vtype property (http://docs.sencha.com/ext-js/4-0/#/api/Ext.form.field.VTypes ).

Free data! Really Simple Web Service Integration using the Yahoo Query Language (YQL)

The YQL Console

The YQL Console highlighting Zillow data

Yahoo has started an ambitious project that aims to open up data to developers by starting the YQL project, which contains data tables from major applications, like real time traffic, zillow home prices, weather, financial information, flicker, social media, the list goes on and on and on, and anyone with an imagination could have a field day writing applications based on the data tables. So how does this all work? First of all YQL uses an SQL like syntax, so if you are familiar with queries such as select * from tablename you will have no problem getting data from an YQL table. Yahoo has built a convenient console that lets you explore the various tables and perform queries before you put the data call into your code, you can access this console here: http://developer.yahoo.com/yql/console/ . There are some queries that require a login and some that do not, so if you want to see all of the possible tables you will have to log in to Yahoo using a yahoo user name and password.

Now that all of the introductions are out of the way let’s take a look at an example that will return the change in stock price using PHP, we will need to run a query against the Yahoo finance data which you can test here by entering a stock symbol that you know off the top of your head like GOOG, MMM, F, or GD and see the decoded JSON come back from the YQL query:

Ticker:

Here’s the code:

<h2>Using YQL to Access the Upcoming API</h2>
<form name='stock'>
Ticker: <input name='ticker' id='ticker' type='text' size='20'/><br/>
<p><button id='find_stock'>Show me the stock information</button></p>
</form>

<script>
  // Attach event handler to button
  document.getElementById("find_stock").addEventListener("click",find_stock,false);
  // Get user input and submit form
  function find_stock(){
    document.stock.ticker.value = document.getElementById('ticker').value || "F";
    document.stock.submit();
  } 
</script>
<?php
  $BASE_URL = "http://query.yahooapis.com/v1/public/yql?";

  if(isset($_GET['ticker']) ){
    $location = $_GET['ticker'];
    $events="";
     
    // Form YQL query and build URI to YQL Web service
    $yql_query = "select * from yahoo.finance.quotes where symbol in ('$location')";
    $yql_query_url = $BASE_URL . "q=" . urlencode($yql_query) . 
"&format=json&env=http%3A%2F%2Fdatatables.org%2Falltables.env";

    // Make call with cURL
    $session = curl_init($yql_query_url);
    curl_setopt($session, CURLOPT_RETURNTRANSFER,true);
    $json = curl_exec($session);
    // Convert JSON to PHP object 
    $phpObj =  json_decode($json);
   
    // Confirm that results were returned before parsing
    if(!is_null($phpObj->query->results)){
      //// ->query->results->quote->ChangeFromYearLow;
       echo var_dump($phpObj);
       }
    // No results were returned
    if(empty($phpObj->query->results)){
      $events = "Sorry, no stock information for ticker symbol $location";
    }
    // Display results and unset the global array $_GET
   
    unset($_GET);
  }
?>

The ExtJs editable grid in a nutshell – part 1 setting up your grid.

One of the biggest problems I faced when developing a good editable grid is the ability to properly populate the dynamic drop-down boxes within the table. ExtJS performs this task much better than most of the packages that I have worked with so far. The following will walk you through and explain an editable grid that has been created using MySQL, PHP and ExtJS. In order to replicate the program you will have to create a table that holds the options, so open MySQL and run the following script (assumes that a database named ‘test’ has been created:

CREATE  TABLE IF NOT EXISTS `test`.`some_options` (
`so_pk_id` INT NOT NULL ,
`option_name` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`so_pk_id`) )
ENGINE = MyISAM;

Insert into test.some_options (so_pk_id,option_name) values ('1','Red')
Insert into test.some_options (so_pk_id,option_name) values ('2','Yellow')
Insert into test.some_options (so_pk_id,option_name) values ('3','Green')

Now we need some fake data for out table, so let’s create the following which will be the table that we will be editing via our editable grid.

CREATE  TABLE `test`.`light_test` (
  `pk_light_id` INT NOT NULL ,
  `color` INT NULL ,
  `name` VARCHAR(45) NULL ,
  `location` VARCHAR(45) NULL );

Insert into test.light_test (pk_light_id,color,name,location) values ('1','2','Some Light','Around the corner')

Ok now that we have the tables set up we will need to create a few pages that will fetch the data from our database and place them into what Ext calls stores, these data stores will contain the original values.

First we will need to connect to the ‘some_options’ table that was created above and get all of the data from the table into a nice JSON string. Fortunately, this is much easier than it sounds when using PHP since there is a handy function called json_encode() that returns the query results in a JSON string, so the code to do this is as follows:

<?php
// The source code of optionsstire.php
$dbhost = '127.0.0.1:3306';
$dbuser = 'test_user';
$dbpass = '';

$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die  ('Error connecting to mysql');

$dbname = 'test';
mysql_select_db($dbname);

$query = "select * from some_options";

 
$result = mysql_query($query);
$num = mysql_numrows($result);
$options = array("results" => $num);
$i = 0;
  while ($row = mysql_fetch_assoc($result)) {
    $options["data"][$i] = $row;
    $i++;
  }
  echo json_encode($options);
?>

…. and of course we need the same code for the main data grid store, which in reality is as simple as changing the line $query = “select * from some_options”; to $query = “select * from light_test”; ..

Now that the foundation has been put in place let’s move on to those stores that were mentioned above. In order to get data into your drop down box, or data grid you will need to connect the data in the lookup table that is in the database with the drop down or combo box. The code for a simple JSON store that matches the PHP code above is:

var option_dd_store = new Ext.data.JsonStore({
            storeId:'option_dd_store',
            autoLoad: true,
            url:'optionsstore.php',
            idProperty:'',
            root:'data',
            totalProperty: 'results',
   fields:[
    { name:'so_pk_id',type:'int' },
    { name:'option_name',type:'string' }
    ]
});

The url property above contains the location to the PHP page that is querying the database. Autoload will ensure that the data is loaded in the store on page load and not at a later time. The fields must match the names given in the JSON file. We will also need a store that contains the data fro the main grid that this combo box will reside in, this code is :

var stoplight_grid_store = new Ext.data.JsonStore({
  storeId:'stoplight_grid_store',
  autoLoad:true,
  url:'mainGridStore.php',
  idProperty:'pk_light_id',
  root:'data',
  totalProperty: 'results',
        fields: [
            {name:'pk_light_id',type:'int' },
            {name:'color',type:'int' },
            {name:'name',type:'string' },
            {name:'location',type:'string' }
        ]
});

Now we need the code that creates the drop down box itself:

var options_dd = new Ext.form.ComboBox({
  triggerAction: "all",
  store: option_dd_store,
  displayField:'option_name',
  valueField:'so_pk_id',
  hiddenName:'so_pk_id'
});

Notice that we defined the store by passing the store variable, and we also defined a hiddenName, and value field as well as the displayField. The hidden field will become extremely important when we want to start passing the variable back to a page that will save the data to the database when it changes on the client side. Now it is time to place the code for the grid on the page.

var exec_type_rpt_sg_grid = new Ext.grid.EditorGridPanel({
          title: 'Stop Light Change Plan',
          store: 'stoplight_grid_store',
          id:'stoplight_grid',
          renderTo:'light_div',
          layout:'fit',
          height: 300,
          columns:[{
                          xtype: 'gridcolumn',
                          header: 'Light Color',
                          sortable: true,
                          resizable: true,
                          
                          width: 150,
                          dataIndex: 'color',
                          editor: options_dd,
                          renderer:function(value)
                                  { 
                                  var index = option_dd_store.find("so_pk_id",value);
                                  var displayName = option_dd_store.getAt(index).get("option_name"); 
                                  return displayName; 
                                  }
                       },{
                          xtype: 'gridcolumn',
                          header: 'Name',
                          sortable: true,
                          resizable: true,
                          width: 300,
                          dataIndex: 'name'
                       },{
                          xtype: 'gridcolumn',
                          header: 'Location',
                          sortable: true,
                          resizable: true,
                          width: 500,
                          dataIndex: 'location'
                       }
          ]
       });

So here is where the real world part of the example comes into play, when you have a table that contains lookup data in another table the main table (above) usually only has a reference to the primary key of the lookup table, so in order to display the ‘displayValue’ from your combo box in the grid opposed to the numerical value that would be the key you will need to use the renderer above which takes the vale from the grid and references it to the options_dd store and then returns the corresponding key.

Later this week we’ll go over updating the database behind the grid, but for now you have the ability to place a dependent dropdown box in the ExtJS grid and have the display value show opposed to the key.

A little bit about JSON

A little bit about JSON, or Javascript Object Notation. As you start using the Javascript Ajax libraries, you will certainly run into JSON so it is extremely important that you get a handle on the basics of JSON.

The basic format of a properly formatted JSON string is:

{ name:'value',name:'value',name:[{sub_value:'value',sub_value:'value'},
{sub_value:'value',sub_value:'value'}]}

The values in the example above are in quotes due to the fact that they strings, if you had numeric values the quotes would be optional, as with boolean values and null. Let’s take a look at how this translates in the real world. Suppose we had the following table in a database that contained name, age, and gender.

Name Age Sex
Barney Rubble 32 Male
Fred Flintstone 33 Male
Betty Rubble 32 Female
Pebbles 1 Female
Bamm Bamm 2 Male




The JSON representation of this table would then be:

{results:5,data:[{name:'Barney Rubble',age:32,sex:'Male'},
{name:'Fred Flinstone',age:33,sex:'Male'},
{name:'Betty Rubble',age:32,sex:'Female'},
{name:'Pebbles',age:1,sex:'Female'},
{name:'Bamm Bamm',age:2,sex:'Male'}]}

You probably will not want to write the JSON by hand as in the example above, so in real life you would write a function that would convert the data from a table into the JSON format. A sample function might look like :

<cffunction name="getFlinstones" hint="get all the flinstones" returntype="string" >

<cfquery name="getData" datasource="flinstoneDB" >

        Select name, age, sex from flinstones

</cfquery>
<cfset json = "{results:#getData.recordcount#,data:[" >
<cfloop query="getData">
     <cfset json = json + "{name:'#getData.name#',age:'#getData.age#',sex:'#getData.sex#'}," >
</cfloop>
<cfset json = Trim(json)>
<cfset json = left(json, len(json)-1)>
<cfset json = json + "]}">
<cfreturn json>
</cffunction>

Of course most languages come with Json support like php: http://php.net/manual/en/book.json.php or cold fusion: http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=JavaScriptFcns_07a.html.

Look for the editable Json grid next.