Showing posts with label ExtJS. Show all posts
Showing posts with label ExtJS. Show all posts

February 23, 2011

Multiple file upload using ExtJS & ASP.Net MVC

Recently I had to build an image gallery for one of my project which used ExtJS & ASP.Net MVC. The gallery consisted of many components, and I will explain the multiple image file upload functionality used in this gallery.


There are many ExtJS plugins already available for file upload that uses flash. One of my requirements was to avoid flash in my project. So, I could not use plugins like
Awesome uploader or UploadForm. So, if you need some fancy looking component & functionality, I suggest you have a look at them as well!

Here I have a simple uploader form that can be used for any server side. I will be using ASP.Net MVC. I have clean URLs as my application follows REST. Let’s have a look at the javascript first:
UploaderWindow =  Ext.extend(Ext.Window,{
    title: 'Upload Window',
 closeAction: 'close',
 id: 'upload-window',
 folderID: null,
 initComponent : function() {
  
  // Upload Form
  var uploadForm = new Ext.form.FormPanel({
   id: 'upload-form',
         fileUpload: true, 
         frame: true,  
   border: false,      
         bodyStyle: 'padding: 10px 10px 0 10px;',
   labelWidth: 50,
   defaults: {
          anchor: '100%'
         },          
   items: [{
             xtype: 'hidden',
             name: 'fieldCount',
    id: 'fieldCount',
    value: 0             
   },{
    xtype: 'hidden',
    name: 'folderID',
    id: 'folderID',
    value: 0
   },{
             xtype: 'fileuploadfield',
             emptyText: 'Select an image',
             fieldLabel: 'Image',
             name: 'file0'            
   }],
   buttons: [{
    text: 'Add File',
    iconCls: 'add_icon',
    handler: function(button,event) {
      
     var fIndex = parseInt(uploadForm.findById('fieldCount').getValue()) + 1;
     uploadForm.add(newField('file' + fIndex));
     uploadForm.findById('fieldCount').setValue(fIndex);
      
     uploadForm.doLayout();
            
    }
   },{
    text: 'Upload',
    handler: function(button, event){
     
     if (uploadForm.getForm().isValid()) {
      uploadForm.getForm().submit({
       url: '/Gallery/Upload',
       waitMsg: 'Uploading your photo...',
       success: function(form, o){        
        alert('Successfuly uploaded!');
       },
       failure: function(form, o){
        alert('Error in uploading the files');
       }
      });
     }
    }
   },{
    text: 'Cancel',
    handler: function() {
     var win = Ext.getCmp('upload-window');
     win.close();
    }
   }]
  });
  
  // Initial Configuration for the window
  var initConfig = {
   resizeable: false,
   modal: true,
   frame: true,
   width: 400,
   autoHeight: true,
   items: [uploadForm]
  };
  
  Ext.apply(this, Ext.apply(this.initialConfig, initConfig));
        UploaderWindow.superclass.initComponent.call(this);
 },
 onRender: function(){
  var fidField = this.upForm.findById('folderID');
  fidField.setValue(this.folderID); 
  UploaderWindow.superclass.onRender.apply(this, arguments);
 } 
});
I have extended Ext.Window class to create my component. The window provides all the controls necessary to upload multiple files onto the server. The upload form is basically embedded within the window. This helps in reuse of the entire component and also helps in customization. In the new component, we have some custom parameters. Once, such parameter is folderID (the default value is null). But when the upload window is created, I would pass a real value. On the server side, the uploaded images are stored according to the folderID passed.



The initComponent method is used to initialize the component. I have the form panel and its elements defined here. Note that I a hidden field to hold the number of files being uploaded (fieldCount) and is set to zero. I also have a field to hold the folder information. This hidden field is populated when the window is instantiated. The file selection functionality is provided by the well known ExtJS component: FileUploadField.

Each time the user click on “Add File” button, we create a new element of the type FileUploadField. This is done with the help of newField method:
function newField(name) {
    var rulesField = new Ext.ux.form.FileUploadField({
        name: name,
        emptyText: 'Select an image',
        fieldLabel: 'Image'
    });
    return rulesField;
}
Now, let’s have a look at the server side code. Our server side is accessed through the URL /Gallery/Upload and the method will be obviously POST. One of my requirements was to upload only images so; I added a simple check for the file extension on the server side. You could do the same on the client side as will. Here is the server side code:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Upload()
{
    string[] supportedTypes = new string[]{ "png", "gif", "jpg", "jpeg" };
    int count = int.Parse(Request.Params["fieldCount"]);
    int folderID = int.Parse(Request.Params["folderID"]);
    
    try
    {
        for (int i = 0; i <= count; i++)
        {
            HttpPostedFileBase postedFile = Request.Files["file" + i];
            if (postedFile != null)
            {
                string x = Path.GetExtension(postedFile.FileName);
                if (supportedTypes.Contains(x.TrimStart('.')))
                {
                   // Process the image
                } else {
                   // document not supported!
                }
            }
        }
        
    }
    catch (Exception e)
    {
        
    }
}
Improvements: There is always space for improvements. You can go ahead with lots of modifications to this component. By end of the day, I had lot of changes. Few improvements are:
  1. Removing added files from the form. 
  2. Client side validations.
  3. Option for entering meta data for the images being uploaded.
  4. Progress bar like other components mentioned above. .. etc 
Your comments are welcome. Enjoy coding! :)

Read other ExtJS related articles!

January 28, 2011

Cascading Combo box in ExtJS

This week, two Techno Paper readers had approached me with questions on cascaded loading of combo box in ExtJS. Rather than replying them with mails, I decided to put it up for on the blog so other readers can also get it. In this tutorial I will explain how to cascade the loading of combo box options.


Cascading combo box can help in avoiding huge combo boxes. You can provide the user with a drill down of options that you offer and this helps them narrow down the options to select. When you have large data to display, it would be better to avoid combo boxes and go for a list view.

For now, let’s take a simple form where the user is asked to select geographical location & language. The selection of city is made by selecting country and region. So, we have three combo box:
  • To select region (Continent)
  • To select country
  • To select city
User does a drilldown on these three combos to finally select the city. First the user selects the continent. Selection triggers loading of all the countries in that continent. And similarly selection of country will trigger the loading of cities of that country.

Now, let’s get our hands dirty with the code. We will have a data store for each of the comobo boxes. In this tutorial, we will use Json store. You should be able to use any other store Ext JS library provide. Let me introduce the store for holding continents:
var mainStore = new Ext.data.JsonStore({
 autoLoad: true,
 url: '/GetContient',
 fields: ['item','value']
});
The store is very simple and straight forward. We set three properties of the json store. Unlike other dropdowns, the continent is starting point of our cascading. In order to load it along with the form, we will use autoLoad property of the stores. You need to define the url from which the store will be loaded & the fields array provides information on the fields.

The other two stores are slightly different. They will be loaded through selection of the respective drop downs. So, they are not initially loaded with values. Here are the stores for country and city:
var countryStore = new Ext.data.JsonStore({
 autoLoad: false,
 pruneModifiedRecords: true,
 url: '/GetCountry',
        fields: ['item', 'value']                   
});
     
var cityStore = new Ext.data.JsonStore({
 autoLoad: false,
        pruneModifiedRecords: true,
        url: '/GetCity',
 fields: ['item', 'value']                   
});
We have set pruneModifiedRecords property inorder to clear records each time the store is loaded. Now we have our stores ready. Let’s code our form and its fields.

Apart from the three drop downs, I will have a text field for keying in the language. We will render the directly onto the HTML document’s body tag. So, here is the code:
var Example = new Ext.Panel({
    title: 'Example of Cascading combos',
    renderTo: document.body,
    width: 400,       
    frame: true,
    items: [{
        xtype: 'form',
        url: '/FormSubmitURL',
        id: 'ex-form',                                                                      
        method: 'post',
        defaults: {
            anchor: '95%'
        },
        items: [{
            xtype: 'combo',
            fieldLabel: 'Continent',
     emptyText: 'Select a Continent',
            store: mainStore,                            
            editable: false,
            allowBlank: false,
            forceSelection: true,
            valueField: 'value',
            displayField: 'item',
            triggerAction: 'all',
            hiddenName: 'continent',
            id: 'continent',
  listeners: {        
          'select' : function(field,nval,oval) {
    countryStore.load({
                      params: {'id': nval.data.value }
             });
    }
   }
        }, {
   xtype: 'combo',
            fieldLabel: 'Country',
   emptyText: 'Select a Country',
            store: countryStore,
   mode: 'local',
            editable: false,
            allowBlank: false,
            forceSelection: true,
            valueField: 'value',
            displayField: 'item',
            triggerAction: 'all',
            hiddenName: 'country',
            id: 'country',
   listeners: {
    'select' : function(field,nval,oval) {
     cityStore.load({
                params: {'id': nval.data.value }
             });
    }
   }
  },{
   xtype: 'combo',
            fieldLabel: 'City',
   emptyText: 'Select a City',
            store: cityStore,
   mode: 'local',
            editable: false,
            allowBlank: false,
            forceSelection: true,
            valueField: 'value',
            displayField: 'item',
            triggerAction: 'all',
            hiddenName: 'city',
            id: 'city'       
  },{
   xtype: 'textfield',
            fieldLabel: 'Language',
            name: 'language',
            id: 'language'
        }],                        
        buttons: [{
            text: 'Submit',
            handler: function() {
    alert('Submit the form');
   }
        }]
    }]
});
Now, lets focus on one of the combo boxes. Notice how we cascade the loading of the combo boxes using the select event. The select event callback function provides us with all the information we need. It has three parameters and they are:
  1. The combo box
  2. The newly selected field record
  3. Numerical index value of old selection
From the callback’s parameters, we get the new selection information, which is used to load the country or city data store using the load method.

You can download the Javascript source code and try it. I have not included the any server side or ExtJS files with the package. Please provide your comments and suggestions. :)

Read other ExtJS related articles!

January 18, 2011

Working with .Net serialized dates in ExtJS

ASP.Net’s JSON serialize encodes DateTime instance as a string. If you return a JSON from a MVC contoller, you will notice your data encoded in the form:
\/Date(1295163209177)\/

This is basically nothing but Jan 16 2011 10:33:29! ExtJs components like data grid, datepicker do not consume this format and needs to be transformed.

Why does Microsoft serialize DateTime in this form?

One of the major disadvantages of using JSON is its lack of date/time literal. The support for date and time values is provided by the Date object in javascript. So, In order to represent the date and time, there are two options available:

1. To express the data as string
2. To express it in numerical form.

The numeric form would be the the number of milliseconds in Universal Coordinated Time (UTC) since epoch. But in either form, we still have the issue of not being able to identify it as date / time. In order to overcome this, MS came up with encoding DateTime values as string in the form:
\/Date(ticks)\/

How to fix it in ExtJS?

Deserializing in ExtJS can be done with the help of Date class. You can use the parseDate static method to convert the serialized date into Date object.
var dt = Date.parseDate(date,'M$');
dt.format('d/m/y');
The deserialized dates can be displayed in any desired format! :)

Read other ExtJS related articles!

January 10, 2011

Creating toolbar in ExtJS Viewport

Building application UI using Ext JS can be complex and confusing for new comers. When you build applications, you usually make use of the border layout for placing different components onto the main screen of your application. In most of the cases you will require a toolbar with menus and buttons. But the viewport component has a catch.


Unlike the panel component of Ext JS, Viewport does not have a tbar option. So, you cannot attach a toolbar component into viewport. The best solution is to convert north region of your application to a toolbar.

To keep things simple, will have north, west and center regions of my border layout. I will also avoid handler methods and other actual content of the application. First lets simple define the application layout alone.
var application = new Ext.Viewport({
    renderTo: document.body,
    layout: 'border',
    items: [{
        region: 'north',
        border: false,
        frame: true,
        html: 'this is north'        
    }, {
        region: 'west',
        layout: 'fit',
        width: 200,
        border: true,
        frame: true,
        html: 'This is the left panel'
    }, {
        region: 'center',
        html: 'This is the center panel',
        frame: true,
        border: true
    }]
});
Once you have the layout, you just need to convert the north region into a toolbar. To do so, you will have to create a tbar instance in the north region’s panel. The complete code given below:
Ext.onReady(function(){
    Ext.QuickTips.init();
        
    var application = new Ext.Viewport({
        renderTo: document.body,
        layout: 'border',
        items: [{
            region: 'north',
            border: false,
            tbar: [{
                text: 'New',
                menu: [{
                    text: 'Add New X'
                }, {
                    text: 'Add New Y'
                }]
            }, {
                text: 'Refresh'
            }, {
                text: 'Tools'
            }, '->', {
                text: 'Options',
                iconCls: 'options_icon',
                menu: [{
                    text: 'User Info'
                }, {
                    text: 'Settings'
                }, {
                    text: 'Switch Theme'
                }]
            }, {
                text: 'Help'
            }, '-', {
                text: 'Logout'
            }]
        }, {
            region: 'west',
            layout: 'fit',
            width: 200,
            border: true,
            frame: true,
            html: 'This is the left panel'
        }, {
            region: 'center',
            html: 'This is the center panel',
            frame: true,
            border: true
        }]
    });    
});
You will have to add handlers for the buttons or menu you added to the toolbar. You can add the appropriate handler function to the property named handler. For example, let’s assume we are adding a handler to “Add New X” menu item:
text: 'New',
                menu: [{
                    text: 'Add New X',
      handler: function() {
Ext.Msg.alert(‘Alert’, 'Add new X item!');
} 
                }, {
                    text: 'Add New Y'
                }]
As always your ideas, doubts and comments are always welcome. Also share your experience on web technologies on Techno Paper facebook page!

Read other ExtJS related articles!

December 20, 2010

Creating a simple Border Layout

At times, building a simple thing can become tedious. Especially when you miss simple configurations that make huge impact! This is a back to basics article on how to code a simple border layout in an ExtJS panel.

Let’s make a simple panel with a border layout:
var panel = new Ext.Panel({
 renderTo: document.body,
            title: 'Border Layout',
            layout: 'border',
            width:700,
            height:400,
            items: [{
                region: 'north',
                layout: 'fit',
                frame: true,
                html: 'This is North!',
                height: 150
                
             },{
                region: 'west',
                layout: 'fit',
                frame: true,
                border: false,
                html: 'This is West!',
                width: 200,                
            }, {
                region: 'center',
                layout: 'fit',
                frame: true,
                width: 400,
                html: 'This is Center!',
                border: false
             }, {
                region: 'east',
                layout: 'fit',
                frame: true,
                border: false,
                html: 'This is East!',
                width: 200                
            },{
                region: 'south',
                layout: 'fit',
                frame: true,
                html: 'This is South!',
                height: 150
                
             }]
    });
There are few points to remember when working with border layout. I have listed few important points:
  • When you use border layout, you should always have width and height of the panel defined. If these are not defined, the panel is not displayed properly.
  • North & South region must have height information for proper display.
  • East & West region must have width information for proper display.
  • Center region is a must for the border layout.

Here is the screen shot of our simple panel:

Share your tips with me and keep coding :)

Read other ExtJS related articles!

June 21, 2010

Hiding Series in ExtJS Charts

In the last few posts we saw how to create and handle events in Ext JS charts. We will have a look at some advanced tasks using Ext JS charts. In this post, we will learn how to hide and display a series in a chart.

As usual, I will go with the sales and revenue chart. In our chart we will have two series - Sales and Revenue. We will provide two check boxes to toggle the series' visibility.
Lets begin with the data store (The data store is same as the one used in previous tutorials):
var store = new Ext.data.JsonStore({
fields:['month', 'sales','rev'],
data: [
    {month:'Jan', sales: 2000, rev: 3000},
    {month:'Feb', sales: 1800, rev: 2900},
    {month:'Mar', sales: 1500, rev: 3100},
    .
    .
    .
    {month:'Nov', sales: 2100, rev: 3000},
    {month:'Dec', sales: 2650, rev: 3300}
]
});
The framework does not provide us with APIs for what we are trying to achieve. But before that lets display the chart and the controls without the proposed functionality:
new Ext.Panel({
    title: 'Hiding series in ExtJS Charts',
    renderTo: 'container',
    width:600,
    height:300,
    tbar:[{
         xtype:'checkbox',
         boxLabel:'Toggle Sales',
         handler: function() {
                  alert('Hide / Show Sales');
           }
         },{
         xtype:'checkbox',
         boxLabel:'Toggle Revenue',
         handler: function() {
                  alert('Hide / Show Revenue');
           }
         }],
    items: [{
        xtype: 'columnchart',
        id:'myChart',
        store: store,
        xField: 'month',
        extraStyle: {
                  legend: {
                        display: 'right'
                  }
    },
    series: [{
        yField: 'sales',
        displayName: 'Sales'
        },{
        yField: 'rev',
        displayName: 'Revenue'
    }]
  }]
});
Now we have the chart and the necessary handler methods on the checkbox, let's split the problem into two parts. First is hiding the series in the chart and second is to hide the series name in the legend.

To hide the series, you will have to access the APIs exposed by flash component. The SWF component exposes a method named setSeriesStylesByIndex for setting styles for a series. The method has two parameters - index of the series you are about to modify and the config object that will hold the new style.You can pass the following parameters and its values to the config object:
  • color
  • colors
  • size
  • alpha
  • borderColor
  • borderAlpha
  • fillColor
  • fillAlpha
  • lineSize
  • lineColor
  • lineAlpha
  • image
  • images
  • mode
  • connectPoints
  • connectDiscontinuousPoints
  • discontinuousDashLength
  • skin
  • visibility
For more details on these attributes, have a look at YUI documentation. Back to our method, it will now look something like this:
function setSeriesStylesByIndex(index, styles){
    // Assuming swfObject is an instance of swf available in chart
    swfObject.setSeriesStylesByIndex(index, Ext.encode(styles));
}
Our next hurdle is how to call this method when clicking on our checkbox. To accomplish our task we will use the override method (static method) available in Ext class.
Here is the final code of our function being injected into chart:
Ext.override(Ext.chart.Chart, {
    setSeriesStylesByIndex: function(index, styles){
        this.swf.setSeriesStylesByIndex(index, Ext.encode(styles));
    }
});
If you execute our project and have a look at the chart rendered you will notice that the series display can be toggled but the legend of the chart is not updated properly. To update the chart's legend, we will update the showInLegend property of the series. Each series can be accessed in a chart using the series array. So, to modify the first first series, we just need to use the array notation to access the series and the showInLegend property. For example:
chart.series[0].showInLegend = false;
By just setting the property will not have any effect on the chart. We will have to update the display by calling the refresh method available with the chart object. Here is how our checkbox event handler look finally:
function() { 
var chart = Ext.ComponentMgr.get('myChart');
    if(this.checked) {
         // hide the columns (series in chart)
         chart.setSeriesStylesByIndex(0,
                  {connectPoints: false,alpha:0.0});
         // hide the series label in legend
         chart.series[0].showInLegend = false;
    } else {
         chart.setSeriesStylesByIndex(0,
                  {connectPoints: true,alpha:1.0});
         chart.series[0].showInLegend = true;
    }
    // Refresh the chart
    chart.refresh();
}
You will have to hard-code the appropriate series index so that the correct series properties is modified.The complete code is given below:
new Ext.Panel({
    title: 'Hiding series in ExtJS Charts',
    renderTo: 'container',
    width:600,
    height:300,
    tbar:[{
         xtype:'checkbox',
         boxLabel:'Toggle Sales',
         handler: function() {
             var chart = Ext.ComponentMgr.get('myChart');
             if(this.checked) {
                 chart.setSeriesStylesByIndex(0,
                          {connectPoints: false,alpha:0.0});
                 chart.series[0].showInLegend = false;
             } else {
                 chart.setSeriesStylesByIndex(0,
                          {connectPoints: true,alpha:1.0});
                 chart.series[0].showInLegend = true;
             }
             chart.refresh();
         }
    },{
         xtype:'checkbox',
         boxLabel:'Toggle Revenue',
         handler: function() {
             var chart = Ext.ComponentMgr.get('myChart');
             if(this.checked) {
                 chart.setSeriesStylesByIndex(1,
                          {connectPoints: false,alpha:0.0});
                 chart.series[1].showInLegend = false;
             } else {
                 chart.setSeriesStylesByIndex(1,
                          {connectPoints: true,alpha:1.0});
                 chart.series[1].showInLegend = true;
             }
             chart.refresh();
         }
    }],
    items: [{
        xtype: 'columnchart',
        id:'myChart',
        store: store,
        xField: 'month',
        extraStyle: {
             legend: {
                display: 'right'
             }
        },
    series: [{
        yField: 'sales',
        displayName: 'Sales'
    },{
        yField: 'rev',
        displayName: 'Revenue'
    }]
  }]
});
ExtJS Line Chart showing Sales & Revenue

Well, that's all for now. In the coming weeks we will have some more tutorials on chart and finally build a dashboard. We will also have a look at the new touch UI framework introduced recently.

Read other ExtJS related articles!

June 15, 2010

ExtJS is now Sencha!

The post's heading speaks it all. Yes, Ext JS a javascript UI library has combined forces with jQTouch and Raphael projects. The company's name is being changed to Sencha which is a popular Japanese green tea. It is interesting to see jQtouch and Raphael which are two leading open source projects getting combined.

As a developer using Ext JS, I am very excited to see this merging. I would like to see Ext JS making use of Raphael's graphics capabilities. At the same this, it will be very interesting to see how a jQuery backed mobile web development library is going to fit it. Will they rewrite the library using Ext JS core? Another interesting point is that both Raphael and jQtouch uses MIT license. The company also managed to get hold of Jonathan Stark to maintain jQtouch.

What I would like to see is a better visualization API (charting tools) based on Raphael rather than the YUI charts. It will be also interesting to see how these projects collaborate and how their outcome affects the developer community.

Read other articles and tutorials on ExtJS.

June 03, 2010

Handling Events in ExtJS Charts

After publishing "Getting started with ExtJS Charts" article last week, I got a question on handling event in ExtJS charts. So, in this article we will discuss about the event handling. Before we present the reader’s issue, let’s have a look at how to handle events.


The documentation of chart package is really bad! I wonder why ExtJS team is not updating it. I would actually love to see a java script based chart library (built by ExtJs team) rather than YUI charts being used. Another option for developers would be to use other charting tools available. But for now, let's get back to event handling.

You can attach custom event handlers just like how you do for any other ExtJS component. You can use the listeners property or use methods like on and addListener.

Now if you have a look at the Cart's source code you will find few hidden events:
  • itemmouseover
  • itemmouseout
  • itemclick
  • itemdoubleclick
  • itemdragstart
  • itemdrag
  • itemdragend
Unfortunately, I found some of these not working as it should be. Even forums seem to have less detail about these events.

Item Click Event (itemclick):
Item click event is invoked when a chart item is clicked. With this event you can do drill down, update another chart or do other dynamic effects on the chart. Let’s dive into the code to get a better understanding.

First let’s set up our data store:
var store = new Ext.data.JsonStore({
    fields:['month', 'sales','rev'],
    data: [
            {month:'Jan', sales: 2000, rev: 3000},
            {month:'Feb', sales: 1800, rev: 2900},
            .
            .
            .
     {month:'Dec', sales: 2650, rev: 3300}
 ]
});
We will create a simple column chart using this store:
new Ext.Panel({
    title: 'A Demo Application',
    renderTo: 'container',
    width:600,
    height:350,
    items: [{
 xtype: 'columnchart',     
 id:'myChart',
        store: store,
        xField: 'month',
 yField: 'sales',
 listeners: {
            itemclick: function(o) {
         var record = store.getAt(o.index);
  Ext.Msg.alert('Item Selected',
                    "You Clicked on Sales: " +rec.get('sales') + 
                    " for " + rec.get('month'));
     }
 }      
    }]
});
In the above code, I have used listeners property to specify my itemclick events handler. Using the parameter passed to the event’s method, we will be able to access all the necessary information. Here I am just displaying the value of sales.

Item Mouse Over Event (itemmouseover):
itemmouseover event is fired when user mouse over an item. This can be used for display some dynamic selection. For example, let’s assume we had a data grid with the same values ie sales and revenue and we would like to automatically select the row when use mouse over on an item in the chart.

We will introduce a data grid that will render the same data store. This time, I will make use of the line chart and display both sales and revenue details.
new Ext.Panel({
        title: 'A Demo Application',
        renderTo: 'container',
 layout:'column',
        height: 350,        
        items: [{
     xtype: 'linechart',
     width:600,
          height:350,
     id:'myChart',
            store: store,
     xField: 'month',
     xAxis: new Ext.chart.CategoryAxis({
                 title: 'Month'
     }),
     yAxis: new Ext.chart.NumericAxis({
  title:'USD', 
         majorUnit: 500
     }),
     series: [{
  yField: 'sales',
  displayName: 'Sales',       
     },{
  yField: 'rev',
  displayName: 'Revenue'
            }],
     listeners: {
  itemmouseover: function(o) {
             var myGrid = Ext.getCmp('myGrid');
      myGrid.selModel.selectRow(o.index);       
  }
     }      
 },{
     xtype: 'grid',
     title:'The Sales Grid',
     id:'myGrid',
     store: store,
     height: 350,
     width: 300,
     stripeRows: true,
     sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
     columns:[
  {header:'Month',dataIndex:'month'},
  {header:'Sales',dataIndex:'sales'},
  {header:'Revenue',dataIndex:'rev'}
     ]
 }]
 });

The area of interest would be to see how we did it. Have a close look at the itemmouseover event handler. Basically, the key to manipulation is the object that is passed to the event handler. Using this you will be able to access not only the index but also the chart object itself. The attributes of this object are:
  • Component – The chart component itself.
  • Index – The index position of the item in store.
  • Item – The row from store corresponding to the index. You can access individual attributes of the row.
  • seriesIndex – The index position of the series. The values starts with 0.
  • type – Name of the event
  • x – x coordinate 
  • y – y coordinate

Drag Events:
itemdrag, itemdragstart and itemdragend are used for drag events. I tried making use of these events to make a graph wherein user will be able to drag the points and modify the values. Unfortunately, I am stuck! If I get it running, I will present it in future.

Double Click Event (itemdoubleclick):
I had very bad time working with this event! It just doesn’t get fired. From the forum discussions I see that this event might not be implemented yet. I wonder why, but It would have been great if user can double click on a specific month’s sales and he get it a detail report to download.

Now, lets tackle the reader's problem.

Reader’s problem:
The reader asked how the click event works and how to know which series was clicked.

Solution:
Now, solving this is very easy. You can handle click using the itemclick event and to identify the series and values you can make use of the values provided by the object. Just modify the as shown below:
itemclick: function(o){
 var rec = store.getAt(o.index);
 if(o.seriesIndex==0)
  Ext.Msg.alert('Item Selected',
                "You Clicked on Sales: " +rec.get('sales') + 
                " for " + rec.get('month'));
 else
  Ext.Msg.alert('Item Selected',
               "You Clicked on Revenue: " +rec.get('rev') +
               " for " + rec.get('month'));
}

Well, thats all for now. Let me know your feedback through comments or my contact form. Enjoy the day and time for me to relax!

Read other ExtJS related articles!

May 29, 2010

Working with ExtJS Pie Charts

In the previous post we saw how to create & customize charts using ExtJS. In this post, we will have a look at Pie charts. Pie charts are little different from other charts as they do not have axis and the data displayed is in percentage.

First Pie Chart

Let’s start with the data store. In this tutorial, I am getting the data from a remote URL. My server returns me a set of JSON object with product name and their sales value. Here is the data store:
var store = new Ext.data.JsonStore({
      fields:['product','sales'],
      root: 'rec',
      url: ‘/piechart/data/’
});
Unlike other charts, pie charts do not have axis. So, instead of using xField and yField properties of charts to pass data, we have dataField and categoryField in pie charts. Here is the code for pie chart:
new Ext.Panel({
title: 'Pie Chart',
      renderTo: 'chartDiv',
      width:400,
      height:300,                        
      items: {
            xtype: 'piechart',
            store: store,
      dataField: 'sales',
            categoryField: 'product'
      }
});
Very simple indeed! ExtJS does all the necessary calculations even if you don’t represent the data in percentage.

Adding Legend

Now, let’s add a legend to this chart. Without it, there is no much use in displaying a chart. An important property for styling is extraStyle. It helps you to add extra styles that will add or override default styles of the chart. Here is the final code for the pie chart and panel:
new Ext.Panel({
       title: 'The Pie Chart',
       renderTo: 'chartDiv',
       width:400,
       height:300,
items: {
       xtype: 'piechart',
       store: store,
       dataField: 'sales',
       categoryField: 'product',
       extraStyle: {
            legend:{
                display: 'right',
                padding: 10,
                border:{
                   color: '#CBCBCB',
                   size: 1
                }
            }
        }
      }
 });
While displaying the legend,notice that I have also made some beautification to it. I have provided a thin border using a specific color. There is no chart specific code for displaying legend, so the same code will work for other types of charts as well.

Custom Colors in your Pie chart

By default, ExtJS picks out the colors when rendering the chart. You might find these color shade dull. Lets try to brighten up our chart. I am going to apply a color scheme called Esprit_80s. In order to apply, we need to basically modify the style of series. So we will modify seriesStyles property of our pie chart:
new Ext.Panel({
       title: 'The Pie Chart',
       renderTo: 'chartDiv',
       width:600,
       height:300,
       items: {
           xtype: 'piechart',
           store: store,
           dataField: 'sales',
           categoryField: 'product',
           seriesStyles: {
             colors:['#F8869D','#25CDF2',
                     '#FFAA3C','#DEFE39',
                     '#AB63F6'] //eSprit 80s
            },
           extraStyle: {
                 legend:{
                    display: 'right',
                 padding: 10,
                 border:{
                   color: '#CBCBCB',
                   size: 1
                 }
           }
       }
    }
});

Note that the property colors is used only for pie charts. If you need to change the colors for other charts you will have to use the color property.

Textures & images in your Pie chart

ExtJS also provides us the ability to use images instead of color. So, if you have few texture images or any other images, you can easily substitute them for colors. This is possible through the images property of seriesStyles. I have five simple texture images and here is how I am adding them to our pie chart:
new Ext.Panel({
       title: 'The Pie Chart',
       renderTo: 'chartDiv',
       width:600,
       height:300,
       items: {
           xtype: 'piechart',
           store: store,
           dataField: 'sales',
           categoryField: 'product',
           seriesStyles: {
           images:['images/one.png',
                'images/three.png',
                'images/two.png',
                'images/four.png',
                'images/five.png']
            },
            extraStyle: {
                legend:{
                display: 'bottom',
                padding: 10,
                border:{
                   color: '#CBCBCB',
                   size: 1
                }
            }
       }
   }
});

Apart from these properties, extraStyle can be used to change the font styles as well. Have a look at the APIs and try out different customizations. I will be back with more customization tutorials on ExtJS charts. Let me know your feedback either through comments or using the contact form.

Learn how to Handle events in ExtJS charts or read other articles on ExtJS.

May 19, 2010

Getting Started with ExtJS Charts

The Charts feature in ExtJS is not a new thing, but recently few Techno Paper readers asked me questions regrading the same. This article is about getting started with ExtJS Charts how to do some basic customizations. For now, we will see what kind of charts ExtJS provide and how to get your first chart displayed.

Prerequisites

I assume you already have knowledge in building the UI (panels at least) and have worked on DataStores ( I will be using JSONStore). If you are not ready with these, may be you can have a look at my basic tutorials like "All about...".

What ExtJS offers
ExtJS offers you Line, Bar, Column, Pie and stacked charts. It also offers good amount of customization options as well. All the chart related classes are under the package Ext.chart and Chart is the base class. Apart from the chart classes, the library also provides classes that can be used to customize the axis, series and even the chart display. But note that, ExtJS makes use of Flash to render the charts and its not pure JavaScript component. Internally ExtJS is making use of YUI charts features and classes. Now, lets get started with coding!

Hello World of Charts

Building charts with ExtJS requires three things. The Datastore, the Chart object and a Panel to display the chart. In our first example i am going to keep things very simple. Lets build a DataStore first:
var store = new Ext.data.JsonStore({
fields:['month', 'sales'],
data: [
    {month:'Jan', sales: 2000},{month:'Feb', sales: 1800},
    {month:'Mar', sales: 1500},{month:'Apr', sales: 2150},
    {month:'May', sales: 2210},{month:'Jun', sales: 2250},
    {month:'Jul', sales: 2370},{month:'Aug', sales: 2500},
    {month:'Sep', sales: 3000},{month:'Oct', sales: 2580},
    {month:'Nov', sales: 2100},{month:'Dec', sales: 2650}
]});
I have a simple JsonStore here with the data hardcoded. In later examples, we will be fetching the data through ajax request. In the JsonStore, I have provided metadata and data. The fields attribute describe the fields in my records. The data attribute actually holds the data in the form of JSON. Instead of using JSON, we could also use XML.

Next, to create the chart object. For this example, I have used the line chart. Here is the code:
var chart = new Ext.chart.LineChart({
    store: store,
    xField: 'month',
    yField: 'sales'
});
Its very clean and simple! I have just provided the data store and what has to be plotted along x and y axis. And finally we need to put the chart into display. Here is our Panel:
var Panel = new Ext.Panel({
    title: 'Yearly Sales',
    renderTo: 'chartDiv',
    width: 400,
    height: 200,
    items:[chart]
});
If you are experienced coder I suggest you define the chart object in the panel rather than declaring it separately. Lets begin dig deeper!

Working with Axis

Chat's axis can be configured using xAsix and yAsix properties. There properties can accept objects of CategoryAsix, NumericAxis or TimeAxis. Lets add titles to our chart's axis:
xAxis: new Ext.chart.CategoryAxis({
                 title: 'Month'
                  }),
                  yAxis: new Ext.chart.NumericAxis({
                  title:'USD',
                  majorUnit: 500
                  })
Note that we have made use of CategoryAxis for y-axis as it hold months. Whereas, we have used NumericAxis for x-axis as it represents sales value in USD. I also changed the units in which the x-axis is represented. Check the API for other properties of these classes.

Working with Series

You don't always plot one parameter on a chart. At times, you have multiple data to be visualized onto the charts. Lets take our example of sales per month and add revenue to it. Now we need to plot both sales and revenue for each month. ExtJS allows you to do this by adding series object to the chart. The framework provides five implementations for different types of charts. Let's modify our chart to show revenue as well:
new Ext.Panel({
       title: 'A Simple Chart',
       renderTo: 'container',
       width:600,
       height:300,
       items: {
           xtype: 'linechart',
           store: store,
           xField: 'month',
xAxis: new Ext.chart.CategoryAxis({
                 title: 'Month'
}),
yAxis: new Ext.chart.NumericAxis({
title:'USD',
majorUnit: 500
}),
series: [{
yField: 'sales'
},{
yField: 'rev'
             }]
}
   });
I have kept the series objects very simple. We have just added the data alone. Upon execution, you will notice that it difficult to interpret the data as we do not have a legend on our chart. And that's exactly our next objective. To start with, lets modify the series as:
series: [{
yField: 'sales',
displayName: 'Sales'
},{
yField: 'rev',
displayName: 'Revenue'
 }]
I have just added the displyName property. To complete our modifications we need to do one final task, i.e display the legend!

Working with Extra Styles

extraSyle is an important property for styling your charts. It helps in modifying the colors, fonts, borders for various parts of your chart like axis, data tips, legends etc. First lets add a legend to our existing chart. Here is the code:
new Ext.Panel({
       title: 'A Simple Chart',
       renderTo: 'container',
       width:600,
       height:300,
       items: {
           xtype: 'linechart',
           store: store,
           xField: 'month',
xAxis: new Ext.chart.CategoryAxis({
                 title: 'Month'
}),
yAxis: new Ext.chart.NumericAxis({
title:'USD',
majorUnit: 500
}),
series: [{
yField: 'sales',
displayName: 'Sales'
},{
yField: 'rev',
displayName: 'Revenue'
             }],
extraStyle: {
legend: {
display: 'right'
}
}
}
   });
If you think of more customizations and styling, you need to have a good look at the extraStyle.
Well, that all for now. Feel free to provide me your feedback on this post. Next, we will have a look at pie charts.

February 02, 2010

Access Control in ExtJS applications

When you implement large applications using Ext Js, you will definitely come across access control. Your application will have different type of users and you don't expect all users to have access to all features. Basically may have roles or groups defined for users and the big question is how do you implement it on to the front end of your application.

Before we proceed further you should remember an important point that permissions should be always be implemented on server side and JavaScript security is always secondary! This is because anybody with a JavaScript debugger and other web development tools can easily compromise the client side security. So, what is the use of adding client side security?

The client side security is used to improve user experience and abstract user so that he see only features or data that he have access to. So, the next question is how do we do it?

You will find many ways to implement the access control but the important point is avoiding unnecessary JavaScript logic to be downloaded when your access your application. At the same time, you can implement access control by avoiding code execution if its not available to the user.

Approach 1 : Permission Configuration
This is a simple approach wherein permission configurations is used to handle security. According to the role of the user who is accessing the application, a configuration class is dynamically built. This class is used to decide what the user can access and what not. When the user login to the application a JSON is created with list of accessible features.

Approach 2 : Control through Dynamic JavaScript
In this approach we will generate the JavaScript need for the user. Hence he will not get any code that he is not allowed to execute. When an user login to the application, his role or group to which he belongs to is determined. Using his role, the JavaScript is generated dynamically using a server side script (I used JSPs). The JavaScript file inclusion will look like:
<script type="text/javascript" src="scripts/application.jsp?role=${userRole}"></script>
Inside application.jsp, the administrator menu is only accessible if the user has the appropriate role.
<c:if test="${userRole=='ADMIN'}">

topMenuObject.add({id:'adminMenu',
text: 'Administrator',
handler: adminMenuHandler});
</c:if>

This approach has some disadvantages as well. The development can be little messy because you are coding JavaScript in JSP file. Also, there is an overhead created when you dynamically generate the JavaScript all the time. You will have to use caching mechanism in-order to reduce the overhead.

That's all for now. You are welcome to comment on these approaches and share other techniques if you have.

Read other ExtJS related articles!

December 29, 2009

How To use GroupHeaderGrid Ext JS plugin

GroupHeaderGrid is a custom plugin that implements support for grouping columns in a grid. When you are serious about using ExtJS on your application, I am sure many of you will come across this requirement where you need to group the column headers in display of records. The plugin do not have specific site but was born out collaboration in the Ext Js forum. It all started with this thread. We will have look at how to use the plugin and some simple examples.

Getting the Plugin
You can find few versions listed and available for download in this thread. I will use the plugin the latest version (1.4) which is for Ext JS 3.0. The plugin comes with a CSS and javascript file. The zip file also contains an example.

Installing and Using The Plugin
Installing the plugin is simply copying the script file and CSS file in appropriate directory. These need not be added into the Ext JS folder ( I usually keep the distribution un-touched) and keep separate folders for my extensions and generic components. For example, lets consider a yearly report for a group of companies. The monthly turnover for each subsidy is displayed in the grid. Now, we need to separate data for each quarter.

To use the plugin with the grid you need to create an instance of the plugin and add it to the grid. Here is code snippet for our example:
...
plugins: [new Ext.ux.plugins.GroupHeaderGrid({
rows:[ [                    
{},
{header: 'Q1', colspan: 3, align: 'center'},
{header: 'Q2', colspan: 3, align: 'center'},
{header: 'Q3', colspan: 3, align: 'center'},
{header: 'Q4', colspan: 3, align: 'center'}                    
]]
})]
...
The rows attribute is most important field for the GroupHeaderGrid class. We specify all the header information as rows. In our example, we have only one level of grouped header. The first column ie, Subsidiary is not grouped. The other 12 columns are grouped into quarters. For each grouping we provide the header's label and column span. In the above example, I have provided the header label, column span and text alignment.

If you have another layer of grouped headers, you will have to add an array into the rows attribute. As per the Ext JS forums, the plugin supports unlimited number of headers. I have used only 2 levels so far. Here is the complete example code:
Ext.onReady(function() {
new Ext.Viewport({
layout: 'border',
items: [{
region: 'center',
xtype: 'grid',
title: 'Yearly Report',
store: new Ext.data.SimpleStore({
fields: ['Subsidiary','Jan', 'Feb', 'Mar', 'Apr', 'May',
'Jun', 'Jul', 'Aug', 'Spt', 'Oct', 'Nov','Dec'],
data: [
['OGC', 2300, 4200, 105600, 5000, 15000, 
7000, 8000, 9100, 10000, 11000, 4000, 5000],
['OGH Ltd', 2100, 6700, 209000, 5000, 500,
7800, 8000, 9600, 10600, 11000, 67000,234000],
['T-DEL', 2320, 7100, 240000, 5800, 7500,
7000, 8500, 9200, 10000, 13400, 3300,24000],
['OGC-I&E', 22000, 2300, 1500, 5000, 8300,
7500, 8000, 99900, 10000, 17300, 21000,76000]
]}),
colModel: new Ext.grid.ColumnModel({
columns: [
{header: 'Subsidiary', dataIndex: 'Subsidiary'},
{header: 'Jan', dataIndex: 'Jan'},
{header: 'Feb', dataIndex: 'Feb'},
{header: 'Mar', dataIndex: 'Mar'},
{header: 'Apr', dataIndex: 'Apr'},
{header: 'May', dataIndex: 'May'},
{header: 'Jun', dataIndex: 'Jun'},
{header: 'Jul', dataIndex: 'Jul'},
{header: 'Aug', dataIndex: 'Aug'},
{header: 'Spt', dataIndex: 'Spt'},
{header: 'Oct', dataIndex: 'Oct'},
{header: 'Nov', dataIndex: 'Nov'},
{header: 'Dec', dataIndex: 'Dec'}
],
defaultSortable: true
}),
plugins: [new Ext.ux.plugins.GroupHeaderGrid({
rows: [[                    
{},
{header: 'Q1', colspan: 3, align: 'center'},
{header: 'Q2', colspan: 3, align: 'center'},
{header: 'Q3', colspan: 3, align: 'center'},
{header: 'Q4', colspan: 3, align: 'center'}                    
]]
})]
}]
});
});
And that's it for now.

Read other ExtJS related articles!

November 05, 2009

Dynamic loading of ComboBox using ExtJS

Ext JS provide us with a very flexible ComboBox widget that can be loaded locally or remotely (dynamic loading). You can also load the combo box from the server in response to an event like changing selection of another combo box. In this article I am going to walk you through an example of dynamically loading a ComboBox in a form.

For example, we have simple form to add details of country. The fields are country name, population and population type. I will keep the first two fields as normal text fields and population type as a combo box. Upon loading of the form, we need to retrieve the population type and load it into the ComboBox.

The first step would be to create a data store (Ext.data.Store) to hold our dynamically loaded data. Lets assume I have a server side method at URL /testapp/poptype.json that fetches the data from some data repository. So, here is our data store:
var ds = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({url: '/testapp/poptype.json',method:'GET'}),
reader: new Ext.data.JsonReader({
root: 'rows',
fields: [ {name: 'myId'},{name: 'displayText'}] 
})
});
Please note that to load the data into the data store, I will have to call the load method. Next, we need to bind this data store to our form. The binding is done through the store attribute when we configure the drop down in the form. Here is our form:
var addCountryForm = new  Ext.form.FormPanel({
id:"addCountryForm",
title:"Add Country Form",
height:300,
closable:true,
style: {margin:5},
frame:false,
items:  [{xtype:'textfield',name:'cname',fieldLabel:'Country Name' },
{xtype:'numberfield',name:'pop',fieldLabel: 'Population'},
new Ext.form.ComboBox({                        
fieldLabel: 'Population Type',
hiddenName:'popType',
store: ds,
valueField:'myId',
displayField:'displayText',
triggerAction: 'all',
emptyText:'Select',
selectOnFocus:true,
editable: false                        
})

],
buttons: [{
text: 'Save'
},{
text: 'Cancel'
}]
});
Now, lets have a look at a sample JSON output:
{
"rows":[
{"myId": "PT1" , "displayText": "Small"},
{"myId": "PT2" , "displayText": "Medium"},
{"myId": "PT3" , "displayText": "Large"}
]
}
Hope this article helped you out. Happy coding!

Read other ExtJS related articles!

May 14, 2008

Using Ext JS library in Documentum

Documentum provides a very good framework for web applications called WDK. If you have worked with WDK, I am sure you must have come across the Ajax and webtop examples. When ExtJS 2.1 was released I needed to test it features, and the idea of using Ext in Documentum struck me! Here we will integrate Ext and Documentum in a simple WDK application. We will use WDK widgets to build the regural forms but add Ext Slider widget (not available in WDK) to the form.

Integrating or mashups are not always easy. As web developer we all would think that just adding the Ext java script files to the WDK application folders will be enough to get things started. But that turned out to be wrong. So lets start with troubled water.

Troubled Water
We will have few questions first and try answering them. Where will be deploy our Ext files? Where will we access Ext files from (container JSPs or our custom component JSPs)? I will answer these questions collectively. I assume you already have a skeleton WDK application on your server and I am sure you know our customizations will go into to custom folder.

We will hold all Ext related files in customjs folder under the custom folder. And as any normal WDK application, I will have my configurations in config and create appropriate JSPs. Now lets come to the second question. We will access these files from component JSP and will use complete context path to access the java script files. The reason to use complete context path is that, container JSPs access all java script files from /wdk/include folder. Now you know the folder structure, let move to programming.

Setting up Ext
Like any other Ext enabled application I will have a appjs which hold my custom Ext files. In customjs folder I have two folders : appjs and extjs. extjs will hold all the Ext library and appjs will hold our application.js file. In our application we will just be adding a slider to the Documentum form. My application.js will look like this:
app = function() {   
var sampleSlider; 
var sliderClick = function(slider,event) {

sobject = document.getElementById("agetxt");
sobject.value = slider.getValue();

sobject = document.getElementById("sliderval");
sobject.value = slider.getValue();

}
return {
init:function() {        
sampleSlider = new Ext.Slider({renderTo:'sample-slider',width: 200,minValue: 0,maxValue: 100});
sampleSlider.addListener('dragend',sliderClick);

}   
}; 
}();
Note that I have simply initialized Ext.Slider object and rendered it to "sample-slider". I also have added a listener to listen clicks on the slider. We will come back to this later.

Programming your WDK component
I will just create a simple component with a JSP and a behaviour class. The JSP will have a form that will request Name, Age and a slider with which user can select a value. The user will be able to select his age using the slider. But the demo I have displayed a text field for the Age. Ideally we will not need this and we will use a hidden field to hold data. But why do we need hidden fields? In the behaviour class you will not have direct access to the Ext widgets. But you have access to all WDK widgets. This is where hidden field comes to rescue. From the behaviour class you will be able to access the values user sets using the slider. The listener methods that we attached to the slider helps in storing the slider value to the hidden field in the JSP page.

Finally on running the WDK application you will get a good looking Ext widget. You can download all the files (I only have the components & ext js files). But you will have to build the skeleton by yourself. Let me know if you have better ideas or problems.

March 21, 2008

CRUD application using ExtJS and Java

Finally I have the CRUD application built on ExtJS and Java. CRUD stands for Create Read Update and Delete. This application will show how to build a simple but complete web application. I have used Java as my server side and Oracle XE to store my data. You can use any server side technology and persistence technology. Now let’s look at the application.

March 04, 2008

Getting started with Ext HtmlEditor

This is in response to the first comment I received for my previous post: All about Ext.FormPanel. My reader had requested for an example where HtmlEditor are used. And here is the response! We will learn to create forms that use the WYSIWYG editor provided by Ext.

The Basics
Ext provides developers with a good WYSIWYG editor under Ext.form.HtmlEditor. But making use of it can be bit tricky. The editor provided, is simple yet very powerful. It even has option for source editing apart from other normal options like font size, font family, colour, links etc. The library provides enough options to customize the components to user needs. Below are the important configuration options for the editor:
  • createLinkText – The default text for the create link prompt.
  • defaultLinkValue – The value for the create link value. By default the value is http://
  • enableAlignments – Enable alignment buttons.
  • enableColors – Enable foreground and highlight colour buttons.
  • enableFont – Enables font selection.
  • enableFontSize – Enables the option of increasing font size.
  • enableFormat – Enables the formatting buttons like bold and italic.
  • enableLinks – Enable links button.
  • enableLists – Provides the facility to create numbered and bullet list.
  • enableSourceEdit – Provide provision for source editing.
  • fontFamilies – Used to specify the supported font families. This is an array of font names.

Options like enableAlignments, enableColors are boolean variables and are all set to true by default. A default for will have all the options enabled. In one way, these default values cause trouble. I will explain about the troubles soon.

Now let’s create our first HtmlEditor. Out approach will be to create a simple feedback for where will ask users to enter name, email address and suggestion. This suggestion field will be represented as a rich editor. Have a look at the code:
formObject = new Ext.form.FormPanel({applyTo:Ext.getBody(),
title:'Sample form',
bodyStyle:'padding:10px',
labelWidth:60,
items:[new Ext.form.TextField({id:'tf',
name:'uname',
inputType:'text',
fieldLabel:'Name',
allowBlank:false 
}), new Ext.form.TextField({id:'ema',  
name:'email',
inputType:'text', 
fieldLabel:'E-mail'
}), new Ext.form.HtmlEditor({id:'sug',  
name:'suggest', 
fieldLabel:'Suggestion' 
})], 
buttons:[{text:'Submit',handler:buttonHandler}]     
});

Everything looks good and planned? On execution of this code, you will get javascript errors saying tip.register is null!!

The Trouble
We just failed in creating our form. What is the solution to this error? Another problem is that I didn’t get much help from documentation either. But later I figured out the problem was because we didn’t initialize the tool tip.

What is the relation between tool tip class and our editor? A simple fact: the buttons in editor’s tool bar make use of tool tips. We need to initialize QuickTip as follows:
Ext.QuickTips.init();
First HtmlEditor
All you need to do is initialize the QuickTip and then create the form. The tool tip initialization can be done in init method of your class. Here is the final working code:
app = function() {
var formObject;

var buttonHandler = function(button,event) {
alert('You clicked the button!');
};   

return {

init:function() {

Ext.QuickTips.init();  

formObject = new Ext.form.FormPanel({applyTo:Ext.getBody(),
title:'Sample form',
bodyStyle:'padding:10px',
labelWidth:60 ,
items:[
new Ext.form.TextField({id:'tf',
name:'uname',
inputType:'text',     
fieldLabel:'Name',
allowBlank:false  
}),
new Ext.form.TextField({id:'ema',
name:'email',
inputType:'text',
fieldLabel:'E-mail'
}),                
new Ext.form.HtmlEditor({id:'sug',
name:'suggest',
fieldLabel:'Suggestion'                  
})
],
buttons:[{text:'Submit',handler:buttonHandler}]            
});
} 
};
There you go! You have your HtmlEditor and forms working smooth.

The final comments
Ext forms have lots of features and forms are important part of web application. I personally feel Ext’s documentation should provide more explanation on the form elements, submitting and load of forms.

March 02, 2008

All about Ext.FormPanel !

Forms are very important part of a web application. As they play a major role in date collection and manipulation, designing a fully functional form becomes a challenging task. Ext provides all necessary widget required to build complex forms in a simple way. It also has a good validation, submit and data load functionality. I will cover creating and submitting of forms.

February 10, 2008

All about Ext.Button!

I have already demonstrated the difference of ExtJS1.x and 2.0 with a simple "Hello World" program. Now let’s get deeper and this time it’s about buttons in ExtJS. In this article we will cover creating, handling and manhandling of Ext buttons.

Setting up your programming environment:

There isn’t much to this. If you do not have ExtJS 2.0, you need to download the latest version. All you have to do is unzip the downloaded file, place them in a proper folder structure. I usually have a folder structure as shown:



The js folder has all the JavaScript of the application. Inside this folder I have separate folders for different libraries and I store my custom JavaScript files in appjs. Again this appjs can have subfolders to separate JavaScript files module-wise. This might not be the best folder structure but for now we will stick to this. If you are new to Ext you can have a look at my "Hello World" program.

Ok! Now we are ready for some action. Let’s start with creating a simple button.

Creating a Button:

Ext has Button class implement in the base package ie, Ext. To create a button all you have to do is create an instance of this class and specify the attributes. The Button class has a parameterized constructor with one parameter, the button’s configuration!
Here is the code to create a simple button:
buttonObject = new Ext.Button({applyTo:'button-div',text:'Simple Button'});
You will see that we have used two configuration parameters. applyTo is used to specify which HTML element is going to become the button. The HTML element can be DIV, P or SPAN tag. Remember that applyTo should be passed for the button to render. The next parameter is the text of the button itself. Now another way to specify the holding element for button can be done my calling the public method applyToMarkup. The method takes a parameter which is the id of HTML element to which the button will be rendered.

Attaching handlers to button:


There are basically three ways to attach event to the button you created. One is to use the constructor to specify a callback when the button is clicked and the other is to use addListner method. This method is more generic because you can specify action for any type of events on a button.

The first method is by using the constructor you specify the call back function that needs to invoke when the button is clicked. Remember: It’s only for handling button clicks. Have a look at the example below:
buttonObject = new Ext.Button({applyTo:'button-div',text:'Testing',handler:buttonHandler});
buttonHandler is a method defined in our application class as private method. Here is the complete application code:
app = function() {

var buttonObject;

var buttonHandler = function(button,event) {
alert('You clicked the button!');
};

return {

init:function() {
buttonObject = new Ext.Button({applyTo:'button-div',         text:'Testing',
handler:buttonHandler});

} 
};
}();
The second method is to use the setHandler method to set the call back method for click event. The method has only one argument and it’s the call back method.

The third method to attach an action is to use the public method addListener. Through this you will be able to define actions for events like clicking, mouse over, mouse out etc. Take a look at this example
buttonNext = new Ext.Button({text:'Touch me'});
buttonNext.applyToMarkup('nxt-button');
buttonNext.addListener('mouseover',mouseHandler);
The addListener method has four parameters out of which last two are optional. Thus in our above example, we have made use of just the feature of assigning action to certain events. The third argument specifies the scope in which the handler method should be executed and the last argument specifies the object containing handler configuration properties. These properties can be scope, delay etc.

Before we close, there is one more way to attach event handler to button. This can be done by calling on method. This method has the same number of parameters as the addListener method.


Firing and removing handlers:


ExtJS provides a good set of APIs to manipulate events and actions for any component. As its possible for developers to create and attach actions for button, its also possible to manually fire, stop and remove these event and action.

Situations arise wherein you need to fire an event or series of events when one components event is fired. To fire an event manually we have fireEvent method.
This method has variable length argument of which the first argument is the event name that needs to be fired and the rest is the parameters passed to the handler if any.Have a look at the example below:
app = function() {

var buttonObject;
var buttonNext;

var buttonHandler = function(button,event) {
alert('You clicked the button!');
buttonNext.fireEvent('mouseover');
};

var mouseHandler = function(button,event) {
alert('Mouse on me!');
};

return {
init:function() {
buttonObject = new Ext.Button({applyTo:'button-div',
text:'Click me',
handler:buttonHandler});

buttonNext = new Ext.Button({text:'Touch me'});
buttonNext.applyToMarkup('nxt-button');
buttonNext.addListener('mouseover',mouseHandler);
} 
};
}();
Here we manually fire the ‘mouseover’ event for buttonNext when user clicks on the first button. Thus inturn, the mouseHandler of buttonNext is called.

Now, let’s remove handlers attached to the buttons. ExtJS provides two methods to remove a specific handler from an event. Developer as either use removeListener or un method (addListener and on for adding). And finally to remove all the handlers attached, you may call purgeListeners method.

Suspending and Resuming Events:

Adding, firing and removing is not all that. At times you may need to suspend the events so that the handlers are not fired. You can use suspendEvents and resumeEvents method to enable and disable the event firing for a component. For example:
buttonNext.suspendEvents();
This would suspend all event fired by buttonNext object.

Other Methods:


I am not explaining each function explicitly. But I am just covering the major once that a developer needs to know. For complete list of methods refer the Ext API Documentation.

Winding Up:

For a Ext beginner, I hope this will greatly helpful. Please let me know of any mistakes in this tutorial. You can download the final source code from here.

Read other articles and tutorials on ExtJS!

January 26, 2008

Wrapper libraries for ExtJS

Ext JavaScript library, used for building rich internet applications has emerged as a popular and very vast library. The Ext team has recently released 2.0.1 which is a maintenance release and fixes lots of issues it predecessor had. Over time, developers around have created wrapper libraries to make Ext more developer friendly and easier.

Ext makes the complete use of JavaScript to build the rich application. The code to build a page at times becomes quite large (especially if you have lot of components). Using Ext in its raw form can be difficult if you are new to JavaScript. This is mainly because it difficult to debug the js code and Ext still lacks good tutorials. But I have come across many open-source projects that are aimed to make developer’s life easy. All these projects seem to be quite good and moving in positive direction.

ExtTLD: Ext library extension for java developers! You have all Ext components represented in the form of tags. All you have to do is add the TLD library, add JSTL support and Apache commons library to your project. The project is still in beta stage and is available for download. But I am not sure of the license in which this library will be distributed and its Tag source code is not available for download.

To test, I downloaded the library and was programming the next minute. The steps are simple and easy. Have a look at sample code:

<ext:body>
<ext:window title="Testing" width="300" height="300" id="myWindow">
<ext:toolbar>
<ext:toolbar.button text="Button 1" />
</ext:toolbar>
<div style="padding:5px">This is a simple window in Ext </div>
</ext:window>
</ext:body>



MyGWT: This is a java library for Google Web Toolkit. The library helps developer to compile their java code to web applications and has been licensed under LGPL 3.0. The library seems to have stable release but I am not sure if the library supports Ext 1.x or 2.0. The site has enough examples and tutorials to start you up.

Let’s change the platform. The above mentioned wrappers are related to java developers. What about .Net, Rails and ColdFusion developers? Wrapper libraries for these platforms are also available. For Microsoft platform we have Ext Extender controls which is hosted on CodePlex. For Rails we have library provided by GL Networks Inside. ColdFusion developers have two libraries Ext.CFC and cfExt.

I am Java guy and have not tested libraries for .Net and others. May be you should test them and comment about it. So, web developers... What are you waiting for? Checkout the libraries!!!

November 01, 2007

Hello World with Ext JS 1.x and Ext 2.0 JS

Ext JS doesn't require an introduction on my blog. I have already written about it and now I am into it. Ext JS 2.0 beta was out recently and looks really cool with lot of new widgets, layouts etc.. The 2.0 version is definitely going to be a big release. I tried out my old Ext JS test files with the new version and found it incompatible! Some of the basic widget like buttons didn’t render properly. So, what is the difference? How can we get it running? In this article we will go through the setup, tools and compare "Hello World" programs.

The Setup

Setup of Ext is very simple. All you have to do is download the zipped library and extract it on you system. You can put it in the web server directory so that the applications we write will be able to access it. This is how it looks like on my Eclipse or web server:



The red box is the ext folder and files. You can remove the doc and examples when you deploy on your web server. In the blue boxed folder ie, appjs I have my custom javascript files for the web application. Now even if you don’t use Eclipse, a setup like this is enough for you to start programming using Ext JS library.

Tools of trade

The best tool available is Eclipse with the Spket IDE plugin installed. The plugin is free for non-commercial purpose and support many libraries like Laszlo, Silverlight , YUI etc. The Spket site also has tutorials on how to configure the plugins and get you started.

Hello World on 1.x

Ok. Lets get started with programming… Here is the HTML for Hello World program:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="js/extjs/resources/css/ext-all.css">
<script type="text/javascript" src="js/extjs/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="js/extjs/ext-all-debug.js"></script>
<script type="text/javascript" src="js/appjs/index.js"></script>
<!-- A Localization Script File comes here -->
<script type="text/javascript">
Ext.onReady(App.init,App);
</script>
<title>Sample</title>
</head>
<body>
<div id="button-div"></div> 
</body>
</html>
There is not much to explain if you know HTML, but for the first times in Ext JS: Note the standard Ext javascript files included. Remember you can use the ext-all.js instead of the ext-all-debug.js. Also notice we have our own javascript file named index.js which is included before the Ext.onReady method is called. Now let’s have a look at the index.js:
App = function() {

var button;
var buttonHandler = function(button, event) {
alert('Hello World!'); 
};

return {

init: function() {
button = new Ext.Button('button-div',{text:'Hello World',handler: buttonHandler});
}
};
}();
Running this will give you a simple button on top of the web page titled "Hello World". On clicking it you get an alert box saying "Hello World" – That's All!



The Ext applications follow the module pattern described by Eric Miraglia. I will talk about this and Javascript OOP later. For now looking closely at the javascript you will see that when you instantiate a button you provide the DOM element and the object properties. In this case the DOM element is "button-div" and properties are text and handler function.

Hello World on 2.0

This code on Ext JS 2.0 is not going to work! You will get a button without any title and on clicking; you will not get the alert box too. In the latest version, we have lot of changes to the Ext that makes new version stand out among all other javascript libraries. If you do through the API documentation you will see new layout and widgets, changes in API etc. These changes in API cause the above mentioned problem. If you compare the constructor of Ext.Button class, you will notice that the latest version have only one parameter and that is the object configuration. You do not have to pass the DOM as in the case of old version. In Ext 2.0 you can specify the DOM in object configuration or you can make use of the applyToMarkup method. So our program will now look like:
App = function() {

var buttonObject;
var buttonHandler = function(button, event) {
alert('Hello World');
};
return {

init: function() {
buttonObject = new Ext.Button(
{text:'Hello World',handler:buttonHandler}); 
buttonObject.applyToMarkup('button-div');

}
};
}();
Instead of using the applyToMarkup method apply the DOM element you can instantiate the button as :
buttonObject=new Ext.Button({applyTo:'button-div',text:'Hello World',handler:buttonHandler});
Wrap up
Wrapping up .. I will post more on the Ext in coming days demonstrating different widgets and techniques as I study them.