Contents |
In addition to a core javascript library, ExtJS also includes one of the richest sets of Javascript UI widgets available today. We will take a look at a few of the widgets that people use most commonly and how easy they are to work with.
Rather than a boring "Hello World" message box, let's add a little twist. Let's create some code to show the text of the paragraph that was clicked in a message box.
Ext.onReady(function() { var paragraphClicked = function(e) { 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 }); } Ext.select('p').on('click', paragraphClicked); });
There are a couple of 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 <p> 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.
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 ds = new Ext.data.Store({ proxy: new Ext.data.MemoryProxy(myData), reader: new Ext.data.ArrayReader({id: 0}, [ {name: 'company'}, {name: 'price', type: 'float'}, {name: 'change', type: 'float'}, {name: 'pctChange', type: 'float'}, {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'} ]) }); ds.load(); var colModel = new Ext.grid.ColumnModel([ {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'} ]); var grid = new Ext.grid.Grid('grid-example', {ds: ds, cm: colModel}); grid.render(); grid.getSelectionModel().selectFirstRow(); Ext.get('grid-example').show(); });
Note: from the new version Ext 2.0, a new class Ext.grid.GridPanel replaces the old one of Ext.grid.Grid. if you want to successfully run through this example in Ext 2.0+, you may want to replace the line of var grid = new Ext.grid.Grid(...); in above code with the line as below:
var grid = new Ext.grid.GridPanel({el: 'grid-example', ds: ds, cm: colModel});
While this looks like a lot, it is really only seven lines of code in total!
How easy was that? If all went well, you should end up with something that looks close to this:
Of course, there will probably be some details about this code that you may not fully understand at this point (like what the heck is a MemoryProxy?). The point 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 API documentation.
We've only seen the tip of the iceberg here. There are literally dozens of UI widgets to choose from in Ext, including automatic page layouts, tabs, menus, toolbars, dialogs, a tree view and many more. Please explore the examples section of the API documentation for a glimpse of everything that's available.
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):
<div id="msg"></div> Name: <input type="text" id="name" /><br /> <input type="button" id="okButton" value="OK" />
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: [server url], // <-- replace with your url params: 'name=' + Ext.get('name').dom.value, text: 'Updating...' }); msg.show(); }); });
(Note: when you check this example, open the page requesting it to the web server, that is, using http:// and not file:// in the URL.)
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 UpdateManager—this class makes sending an Ajax request, receiving a response and updating another Element extremely trivial. The UpdateManager 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 UpdateManager 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):
from django.http import HttpResponse def ajax_request(request): return HttpResponse('From Server: %s' % request.POST.get('name', 'nada'))
<?php if(isset($_POST['name'])) { echo 'From Server: '.$_POST['name']; } ?>
#!/usr/bin/perl use strict; use warnings; use CGI; my $Query = new CGI; print $Query->header(); print "Hello from : ".$Query->param('name'); exit;
protected void Page_Load(object sender, EventArgs e) { if (Request.Form["name"] != null) { Response.Write("From Server: " + Request.Form["name"]); Response.End(); } }
<cfif StructKeyExists(form, "name")> <cfoutput>From Server: #form.name#</cfoutput> </cfif>
From Server: ${param.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!