Articles: 843 | Categories: 148   
   
   
Home Articles Contact Us
 
 
 
 
Introduction to Ext 2.0 (0 Comments)
Admin: Posted Date: April 4, 2010

 Anyone new to using the Ext library or trying to learn more about it has come to the right place. This tutorial will walk through Ext basic concepts and how to get a dynamic page up and running quickly. It is assumed that the reader has some Javascript experience and a basic understanding of the HTML document object model (DOM).

Introduction to Ext 2.0

Anyone new to using the Ext library or trying to learn more about it has come to the right place. This tutorial will walk through Ext basic concepts and how to get a dynamic page up and running quickly. It is assumed that the reader has some Javascript experience and a basic understanding of the HTML document object model (DOM).

Set Up Ext

If you haven't done so already, you'll first want to get Ext set up.

Let's Get Started

We're going to walk through some of the most common tasks that people have to accomplish in Javascript and how to perform them using Ext. 

This zip contains four files: ExtStart.html, ExtStart.js, ExtStart.css and ajax-example.php.

  • Unzip all 4 files into a folder directly under the folder where Ext is installed (for example, if Ext is at "C:\code\ext-2.0\," create a new folder under "ext-2.0\" called "tutorial" ie. "C:\code\ext-2.0\tutorial\").
  • Double-click ExtStart.html so that it launches in your default web browser, and you should get a message telling you that everything is configured correctly. If you get a JavaScript error, please follow the instructions on that page to get it working.

 

Now you're ready to open ExtStart.js in your favorite IDE or text editor and take a look at it:

Ext.onReady(function() {
alert("Congratulations!  You have Ext configured correctly!");
});

Ext.onReady is probably the first method that you'll use on every page. This method is automatically called once the DOM is fully loaded, guaranteeing that any page elements that you may want to reference will be available when the script runs. You can go ahead and delete the alert() line now so that we can start adding some real code that actually does something useful!

Element: The Heart of Ext

Almost everything you do in Javascript will at some point involve referencing specific elements on your page so that you can do interesting things with them. Using traditional Javascript, selecting a DOM node by ID is done like this:

var myDiv = document.getElementById('myDiv');

This works just fine, but the object that is returned (a DOM node) doesn't offer much in the way of power or convenience. In order to do anything useful with that node, you are left still writing a lot of custom plumbing code yourself. Plus it is your responsibility to handle all of the differences in how the node can be used from browser to browser, which can be daunting.

Enter the Ext.Element object. The Element really is the heart of Ext as most of what you'll do involves getting access to Elements and performing actions on them. The Element API is fundamental to the entire Ext library, and if you spend the time to really learn only one class in Ext well, Element should be it!

The corresponding code to get an Ext Element by ID looks like this (the starter page ExtStart.html contains a div with the id "myDiv," so go ahead and add this code to ExtStart.js):

Ext.onReady(function() {
var myDiv = Ext.get('myDiv');
});

So we are getting back an Element object now—what's so interesting about that?

  • Element wraps most of the DOM methods and properties that you'll need, providing a convenient, unified, cross-browser DOM interface (and you can still get direct access to the underlying DOM node when you need it via Element.dom)
  • The Element.get() method provides internal caching, so multiple calls to retrieve the same object are incredibly fast
  • The most common actions performed on DOM nodes are built into direct, cross-browser Element methods (add/remove CSS classes, add/remove event handlers, positioning, sizing, animation, drag/drop, etc.)

This means that you can do all kinds of useful stuff with very minimal code. Here are just a few simple examples. Go ahead and try adding some of these to ExtStart.js after the previous line where we got the 'myDiv' Element:

myDiv.highlight();      // The element's background will highlight to yellow then fade back
myDiv.addClass('red');  // Add a custom CSS class (defined in ExtStart.css)
myDiv.center();         // Center the element in the viewport
myDiv.setOpacity(.25);  // Make the element partially-transparent

Selecting DOM Nodes

Often it is either impractical or impossible to select DOM nodes by ID. Maybe the ID is not set, or you don't know it, or there are too many elements to practically reference directly by ID. Sometimes you may want to select nodes based on something other than ID, like an attribute or a CSS classname. For these reasons, Ext ships with an extremely powerful DOM selector library called DomQuery.

DomQuery can be used as a standalone library, but more often when using Ext, you'll use it in the context of selecting Elements so that you can then act on them via the Element interface. Luckily, the Element object itself supports querying via the Element.select method, which internally uses DomQuery to select elements. As a simple example of how you might use this, the ExtStart.html file contains several paragraph (

) tags, none of which have ids. If you wanted to easily select every paragraph and perform an action on all of them at once, you could do something like this:

// Highlights every paragraph
Ext.select('p').highlight();

DomQuery supports a wide array of selection options, including most of the W3C CSS3 DOM selectors, basic XPath, HTML attributes and a lot more. 

Responding to Events

So far in our examples, all of the code we've written has been directly inside the onReady function, which means that it always executes immediately after the page loads. This doesn't give us much control—you will most commonly want your code to execute in response to specific actions or events that you choose to handle. To do this, you define event handlers that can respond to events using functions that you assign.

Let's start off with a simple example. Open up ExtStart.js and edit it so that your code looks like this:

Ext.onReady(function() {
Ext.get('myButton').on('click', function(){
alert("You clicked the button");
});
});

The code still executes when the page loads, but there's an important difference. The function containing the alert() is defined, but is not actually executed immediately—it is assigned as the "handler" of the button click event. Spelled out in plain English, this code might read: "Get a reference to the Element with id 'myButton' and assign a function to be called anytime someone clicks on the Element."

Not surprisingly, Element.select allows you to do the same thing, but with an entire group of Elements at once. For example, to show our message when any paragraph in our test page is clicked, we could do this:

Ext.onReady(function() {
Ext.select('p').on('click', function() {
alert("You clicked a paragraph");
});
});

In these two examples, the event handling function is simply declared inline, without giving it a function name. The term for this type of function is an "anonymous function" since it is declared without ever being named. You can also assign an event to be handled by a named function, which is especially useful if you want to reuse the function and have it handle multiple events. For example, this code is functionally equivalent to the previous example:

Ext.onReady(function() {
var paragraphClicked = function() {
alert("You clicked a paragraph");
}
Ext.select('p').on('click', paragraphClicked);
});

So far we have looked at performing a generic action when our event is raised, but how do we actually know which specific Element raised the event so that we can perform some action on it? It turns out to be pretty easy—the  Element.on method passes three extremely useful parameters to the event handling function (we're only going to look at the first one here, but you should explore the API documentation to learn more about event handling details). In our previous examples our handling function was ignoring these parameters, but with one simple change, we can provide an additional level of functionality. The first, and most important, parameter is the event that occurred. This is actually an  Ext,EvenObject, which is both normalized across browsers and provides more information than the standard browser event. For example, the event's target DOM node can be retrieved with this simple addition:

Ext.onReady(function() {
var paragraphClicked = function(e) {
Ext.get(e.target).highlight();
}
Ext.select('p').on('click', paragraphClicked);
});

Note that target is a DOM node, so we first retrieve the corresponding Element, then perform whatever action we want on it. In this case, we are visually highlighting the paragraph.

Passing Arguments to Event Handlers

var someHandler = function(evt,t,o,myArg1,myArg2,myArg3) {
//do stuff
}
Ext.select('.notice-type1').addListener('click', someHandler.createDelegate(this, [4,'pizza',11], true));
Ext.select('.notice-type2').addListener('click', someHandler.createDelegate(this, [7,'stuff',12], true));

The function someHandler will get called with the following arguments:

evt, t, o
These are the arguments that would get passed to your event handler normally. They are: the EventObject describing the event, the Element which was the target of the event, and the options object from the addListener call. You can also set a breakpoint in Firebug inside your event handler to check these objects out and see what kind of useful things they contain.
myArg1, myArg2, myArg3
your own custom arguments specified as an array which is passed as the second argument to createDelegate. In this case we're passing 4,'pizza',11 for elements of class "notice-type1" and 7,'stuff',12 for elements of class "notice-type2".

If all you want to do is pass custom arguments to the even handler and you don't need to have access to the element that fired the event you're probably better off just using  createCallback


Using Widgets

In addition to the core javascript library that we've been discussing, Ext also includes one of the richest sets of Javascript UI widgets available today. There are far too many to cover in this introduction, but let's take a look at a couple of the widgets that people use most commonly and how easy they are to work with.

MessageBox

Rather than a boring "Hello World" message box, let's add a little twist. We already have code that we wrote in the previous section that highlights each paragraph when you click on it. Let's modify that code to also show the text of the paragraph that was clicked in a message box. In the paragraphClicked function above, replace the line:

Ext.get(e.target).highlight();

...with this code:

var paragraph = Ext.get(e.target);
paragraph.highlight();
 
Ext.MessageBox.show({
title: 'Paragraph Clicked',
msg: paragraph.dom.innerHTML,
width:400,
buttons: Ext.MessageBox.OK,
animEl: paragraph
});

There are a couple of new concepts being shown here that are worth discussing. In the first line, we are now creating a local variable named paragraph that will hold a reference to the Element representing the DOM node that was clicked (in this case we know it will always be a paragraph since our click event is only associated with

tags). Why are we doing this? Well, looking ahead for a moment, we will need a reference to the Element to highlight it, and we'll also use the same Element for some of the MessageBox parameters. In general, it is bad practice to make the same function call multiple times to retrieve the same value or object reference, so by assigning it to a local variable and reusing the variable, we are being good object-oriented developers!

Now, on to the MessageBox call, which demonstrates the other new concept for us to discuss. At first glance, this may look simply like a list of parameters being passed to a method, but if you look closely, there is a very specific syntax. What is actually being passed to MessageBox.show() in this case is only one parameter: an object literal that contains a set of properties and values. In JavaScript, an object literal is a dynamic, generic object that is created anytime you use the { and } characters surrounding a list of name/value properties, and the format for those properties is [property name] : [property value]. You'll see this pattern used extensively throughout Ext, so you should learn it well!

Why use an object literal? The main reason is flexibility. New properties can be added or removed from the object literal at any time, or defined in any order, while the method signature (the number and types of parameters expected by a method) never has to change. It also makes it far more convenient from the end developer's perspective when using methods with many optional parameters (as in the case of MessageBox.show). For example, let's say that a fictional method foo.action has four optional parameters, but you only need to pass one of them. In this case, your code might look like this: foo.action(null, null, null, 'hello'). However, if that method instead took an object literal, the code would look like this: foo.action({ param4: 'hello' }). Much easier to use, much more readable.

Grid

The grid is one of the most popular widgets in Ext, and usually the first one that people want to see, so let's take a look at how easy it is to get a basic grid up and running. Replace any existing code you have in ExtStart.js so that it looks like this:

Ext.onReady(function() {
var myData = [
['Apple',29.89,0.24,0.81,'9/1 12:00am'],
['Ext',83.81,0.28,0.34,'9/12 12:00am'],
['Google',71.72,0.02,0.03,'10/1 12:00am'],
['Microsoft',52.55,0.01,0.02,'7/4 12:00am'],
['Yahoo!',29.01,0.42,1.47,'5/22 12:00am']
];
 
var myReader = new Ext.data.ArrayReader({}, [
{name: 'company'},
{name: 'price', type: 'float'},
{name: 'change', type: 'float'},
{name: 'pctChange', type: 'float'},
{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
]);
 
var grid = new Ext.grid.GridPanel({
store: new Ext.data.Store({
data: myData,
reader: myReader
}),
columns: [
{header: 'Company', width: 120, sortable: true, dataIndex: 'company'},
{header: 'Price', width: 90, sortable: true, dataIndex: 'price'},
{header: 'Change', width: 90, sortable: true, dataIndex: 'change'},
{header: '% Change', width: 90, sortable: true, dataIndex: 'pctChange'},
{header: 'Last Updated', width: 120, sortable: true, 
renderer: Ext.util.Format.dateRenderer('m/d/Y'), 
dataIndex: 'lastChange'}
],
viewConfig: {
forceFit: true
},
renderTo: 'content',
title: 'My First Grid',
width: 500,
autoHeight: true,
frame: true
});
 
grid.getSelectionModel().selectFirstRow();
});

While this looks like a lot, it is really only 4 lines of code in total (3 if you don't count the test data)!

  • The first line of code creates an array of test data to be displayed in the grid. In real projects, you would likely load this data from some dynamic source like a database or web service.
  • Next, we create a data reader that knows how to interpret the data and convert it into usable records for the grid's data store. There are several different types of Reader classes for different types of data.
  • Next, we create the grid widget, passing in all sorts of config values, including:
    • A new data store, configured on the fly with our test data and reader
    • The column model definition using the columns config
    • Additional options to set up specific grid features
  • Finally, we tell the grid to highlight its first row via the SelectionModel.

How easy was that? If all went well, you should end up with something that looks close to this:

Image:IntroToExt2_grid.gif

Of course, there will probably be some details about this code that you may not fully understand at this point. The intent of this example is to show how it's possible to create an extremely rich, visually-complex user interface component with very few lines of code—learning the details will be left as an exercise for the reader. There are many resources to help you with learning the grid, including the interactive grid demos and the .Grid anel API documentation.

Using Ajax

Once you have your page created and you know how to interact with it through Javascript, you'll probably want to know how to get data to and from a remote server, most commonly to load and save data from a database on the server. Doing this asynchronously via Javascript without reloading the page is known commonly as Ajax, and Ext has excellent Ajax support built right in. For example, a common goal is to handle a user interaction, post something to the server asynchronously, then update an element of the UI in response to the action. Here's an example of a very simple HTML form containing a text input field, a button, and a div used to display a message (Note: you can add this code to ExtStart.html if you'd like to follow along, but you'll have to have access to a web server in order to run the server code below):

Name: type="text" id="name" /> type="button" id="okButton" value="OK" />
id="msg">

Next, we'll add the Javascript required to get our data and post it to a server-based process (replace any existing code in ExtStart.js with this):

Ext.onReady(function(){
Ext.get('okButton').on('click', function(){
var msg = Ext.get('msg');
msg.load({
url: 'ajax-example.php', // <-- change if necessary
params: 'name=' + Ext.get('name').dom.value,
text: 'Updating...'
});
msg.show();
});
});

Note: This example will only run from a web server. The URL in your browser should start with http:// and not file:// or the Ajax transaction will not work! Localhost will work fine, but it must be via http.

Hopefully the general pattern is starting to look familiar by now! The code is wrapping the okButton input with an Element object and attaching an anonymous function that will handle the event if anyone clicks on the button. Inside the click handler, we're using a special class built into Ext called the  Update this class makes sending an Ajax request, receiving a response and updating another Element extremely trivial. The Updater can be used directly, or as we're doing here, it can be accessed via the Element that we want to update (in this case the 'msg' div) using the Element.load method. When Element.load is used, the server's response automatically replaces the innerHTML of the Element. Simply pass it the URL to the server-based process that will handle the request, the querystring parameters to process (in this case passing in the value of the 'name' field) and the text to display in the Element's innerHTML while the request is being processed. Show the msg div (since it starts hidden by default) and that's it! Of course, as with most things in Ext, there are many more Updater options supported, as well as different ways to process Ajax requests in different situations but this shows how easy it is to get a basic example up and running.

The last piece of the Ajax puzzle is the process on the web server that actually handles the request and returns a response to the page. This process could be a server page, a servlet, an HTTP handler, a web service, even a Perl or CGI script—just about anything that can reside on a web server and process HTTP requests. Unfortunately, because of this variety there is no way to give a standard example that would cover all possibilities. Here are some examples in a few common languages to hopefully get you started (this code simply echoes whatever was passed from the 'name' field back to the client with 'From Server: ' added at the beginning, and that gets written to the 'msg' div). The PHP example has been included in the download as 'ajax-example.php' but feel free to replace that with your server code of choice:

Plain PHP

 if(isset($_POST['name'])) {
echo 'From Server: '.$_POST['name'];
}
?>

CakePHP

 if(isset($this->data['name'])) {
$this->flash('From Server: '.$this->data['name']);
}
?>

Django

from django.http import HttpResponse
 
def ajax_request(request):
return HttpResponse('From Server: %s' % request.POST.get('name', 'nada'))

Perl

#!/usr/bin/perl
use strict;
use warnings;
use CGI;
 
my $Query = new CGI;
 
print $Query->header();
print "Hello from : ".$Query->param('name');
 
exit;

ASP.Net

protected void Page_Load(object sender, EventArgs e)
{
if (Request["name"] != null)
{
Response.Write("From Server: " + Request["name"]);
Response.End();
//Note: the call to Response.End() will throw an 
//exception (that's what it's designed to do). It's
//OK to simply catch it and ignore it; depending on
//your use case, you may find that necessary. 
}
}

ColdFusion

 StructKeyExists(form, "name")>
From Server: #form.name#

 or using ColdFusion Scripting (cfscript)

if (StructKeyExists(form, "name")) {
writeoutput("From Server : " & form.name);
}

JSTL (JSP)

From Server: ${param.name}

Ruby on Rails

render :text => "From Server: #{params[name]}"

The real challenges when dealing with Ajax processing involve all of the plumbing code required to properly process and format real structured data on the server. There are several formats to choose from that people use commonly (most often either JSON or XML). There are also many language-specific libraries available to deal with Ajax processing that can work well with Ext, as Ext is language-neutral with regard to the server. As long as the result is sent to the page in the proper data format, Ext does not care what happens on the server!

 
 
Add a Comment:
 
(You must be signed in to comment on an article. Not a member? Click here to register)
   
Title:

Comments: