Archive for the ‘Tutorials’ Category

Advanced Plugin Development with Ext JS

Wednesday, November 11th, 2009

When creating a cross browser RIA, choosing a framework with a plethora of components is where most of us look first. There comes a time, however, when the framework might not have the specific component or functionality we need. Here, selecting a framework that enables you the flexibility to enhance and expand its offering becomes very important. Fortunately, Ext JS has all the rich UI functionality that most applications require coupled with a vibrant community creating impressive extensions. However, sometimes, you will want to add extra capabilities to a component for which an extension is not available. Ext’s elegant design allows us to explore our creativity by adding new features to existing widgets. We will explore several ways to approach this advanced task.

What is an Ext Plugin?

An Ext Plugin is a class (It could also be a singleton object) which is configured into a Component in the plugins config option. All plugins must implement a method named init which is called by the Component, passing itself as the sole parameter at initialization time right at the beginning of the Component’s lifecycle, before it has been rendered.

Upon gaining control, a plugin must initialize itself to add capabilities and processing to its client Component.

This is usually done by augmenting certain methods of the client Component by specifying new functions to run either before or after the base Component’s method. This is done using Ext’s additions to all JavaScript functions, createInterceptor or createSequence. Each of these functions will be explained individually as they become relevant.

Approaches to Adding Functionality

When an application developer needs to enhance, or change the functioning of an existing Ext Component there are several options open each of which has advantages and disadvantages.

For example, Ext’s form Fields receive the fieldLabel configuration when used in a Container with a layout of form. Imagine that we want to eliminate this requirement and allow Fields to manually render their own labels. Ext is flexible enough that we can add this functionality in many different ways.

There are three possible options:

Component configuration (Option 1)

The developer may choose to configure the input Fields with listeners on published events which use the published interface of the TextField class to achieve the requirement. This may be done by using the listeners configuration or setting up event handlers after the component is instantiated with the on method.

In a one-off situation, this might be the easiest option, but as soon as the requirement needs to be repeated in different situations, code duplication can arise. In this case, it’s immediately obvious that we cannot add such complex new processing into each configuration of every Field.

Another disadvantage is that events may be programmatically suspended, or may be cancelled by existing event handlers rendering the added listeners inoperative.

Create a subclass (Option 2)

In a subclass, the developer overrides the template methods (more of which later) which provide the structure and lifecycle flow of the Component. The equivalent template method in the superclass is called either before or after the additional functionality is performed.

A possible implementation of a self labeling TextField class.

The disadvantage here is that forking off a subclass at any level in the hierarchy to add capabilities to a class, “strands” any existing subclasses of the augmented class. They are left without access to the extra functionality.

In this case, we’ve created an enhanced TextField which renders its own label, but this leaves subclasses like TriggerField, TextArea and NumberField unable to take advantage of the added functionality.

Another disadvantage is that if there are two subclasses of a base class which both implement some new capabilities, and a developer wants to use both sets of new capabilities, this is not possible.

Create a plugin (Option 3)

This option offers the most flexibility in terms of code reuse because if carefully written, a plugin for one class is usable by subclasses of that class. Also, multiple plugins may be used in a Component. This obviously requires that the plugins do not conflict with each other.

Implementing a Plugin

Before we dive into an implementation, let’s examine how a plugin can entwine its required functionality around the existing functionality in an Ext Component without using events.

We avoid using events because there is no guarantee that our plugin’s listener would be called before or after other event handlers. Other listeners might stop the event by returning false, or events may be programatically suspended.

Instead, we augment methods within the host Component which allows our plugin to gain control at important points in the component lifecycle.

The Template Method Pattern

Ext JS’s Component class hierarchy uses the Template Method pattern to delegate to subclasses, behaviour which is specific only to that subclass.

The meaning of this is that each class in the inheritance chain may ‘contribute’ an extra piece of logic to certain phases in the Component’s lifecycle. At each phase, a class implements its own special behaviour while allowing the other classes in the inheritance chain to continue to contribute their own logic. The template methods are analogous to events, they perform internal processing at defined points in Component lifecycles which loosely correspond to events.

An example is the render function. Instead of having to override it and duplicating its complex code, it provides you with hooks or Template Methods which each subclass can implement. The two hooks that are executed during the render process are onRender and afterRender. Every subclass implementor can add class-specific processing to any template method. By calling the hook on the superclass and up the entire inheritance hierarchy, we allow each class to contribute its own behavior while keeping the inheritance chain in tact.

The diagram above illustrates the execution of the onRender template method up the entire inheritance chain within a Component. When the render method is executed it will call this.onRender which is the implementation within the current subclass (if implemented). For example, if a subclass of Panel called MyPanel is being rendered, MyPanel.onRender is called. This method performs the special processing that makes the class different from the Panel class and calls the superclass version which calls its superclass version etc. Each class contributes its specific functionality, and control eventually returns to the render function.

There are several Template Methods in the Ext JS Component lifecycle which provide useful points to implement class-specific logic.

The Template Methods available to all Component subclasses are:

  • onRender

    Allows addition of behaviour to the rendering phase. After calling the superclass’s onRender, the Component’s Element will exist. Extra DOM processing may be performed at this stage to complete the desired structure of the control.

  • afterRender

    Allows addition of behaviour after rendering is complete. At this stage the Component’s Element will have been styled according to the configuration, will have had any configured CSS class names added, and will be in the configured visibility and the configured enable state.

  • onAdded

    Allows addition of behaviour when a Component is added to a Container. After calling the superclass’s onAdded, the Component will hold a reference to its parent Container in its ownerCt property.

  • onRemoved

    Allows addition of behaviour when a Component is removed from a Container. After calling the superclass’s onRemoved, the Component will have no ownerCt reference.

  • onShow

    Allows addition of behaviour to the show operation. After calling the superclass’s onShow, the Component will be visible.

  • onHide

    Allows addition of behaviour to the hide operation. After calling the superclass’s onHide, the Component will be hidden.

  • onDisable

    Allows addition of behaviour to the disable operation. After calling the superclass’s onDisable, the Component will be disabled.

  • onEnable

    Allows addition of behaviour to the enable operation. After calling the superclass’s onEnable, the Component will be enabled.

  • onDestroy

    Allows addition of behaviour to the destroy operation. After calling the superclass’s onDestroy, the Component will be destroyed.

Further Ext classes down the hierarchy add their own Template methods which are appropriate to their own capabilities. To learn more about adding functionality within template methods read the Creating New UI Controls article in the Learn section of our website.

Hooking into Template Methods

A plugin needs to insert some extra processing either before or after its client Component’s template method executes. To do this, we need to understand how to create function interceptors and function sequences.

Interceptors

An interceptor function is a function which a developer uses to perform some functionality before an existing function performs its own functionality. As an example, let’s insert some functionality before Observable’s fireEvent method so that we can log all Ext events to the Firebug console. (Warning: there will be lots!)

// A class's methods are stored in its <b>prototype</b>, so grab that.
var o = Ext.util.Observable.prototype;
 
// This is the function we will be executing <b>before</b> the real fireEventMethod.
// It will be passed all the same argments, and has the same scope (this reference).
// Log the firer, the event name, and the arguments to the console.
 
function fireEventInterceptor(evt) {
    var a = arguments;
    var msg = "fired the following event {0} with args";
 
    console.log(this);
    console.log(String.format(msg, evt));
    console.log(Array.prototype.slice.call(a, 1, a.length)); 
}
 
// Set the class's fireEvent to be our interceptor.
o.fireEvent = o.fireEvent.createInterceptor(fireEventInterceptor);

It’s that simple. Our function always gets called before Ext’s original fireEvent method.

Sequences

A sequence is a function which gets executed after an existing function.

Our plugin implementation uses sequences to add its own processing after the processing of the Field has taken place.

A FieldLabeler Plugin

In this case, the plugin is a singleton. It cannot be instantiated. It is specified simply using:

plugins: [ Ext.ux.FieldLabeler ]

It augments several of its client Field’s template methods with its own methods. These execute as if they were member methods of the Field. Their this reference is the Field itself, so they can perform any processing which may be necessary at that particular lifecycle phase. This is why a singleton may be used – all contextual information is in the client Component.

The three methods we augment within our plugin are:

  • onRender
    Our added code renders extra DOM elements.
  • onResize
    Our added code ensures the extra DOM elements are sized properly
  • onDestroy
    Our added code ensures the extra DOM elements are cleaned up.

By implementing this functionality as a plugin rather than a subclass we have eliminated the problem of our downstream plugins not receiving the added functionality. This plugin is capable of being integrating with TriggerField, TextArea and NumberField without a problem.

Take a look at the example of this plugin in action here. The source has been comprehensively documented and is available here.

Summary

We explored different ways to implement custom functionality and specifically how to create reusable plugins without creating a fragile class hierarchy. Using plugins to augment Ext’s baseline functionality is one of the best approaches when you want to be able to mix and match functionality. The most important concept to grasp is that we can provide additional functionality by augmenting existing methods within a component that are guaranteed to be executed during a components lifecycle. We encourage you to take a look at the thousands of plugins available on the Ext Forums. We hope that our post and community inspire you to take the plunge into Ext plugin development.

5 Steps to Understanding Drag and Drop with Ext JS

Sunday, September 13th, 2009

One of the most powerful interaction design patterns available to developers is “Drag and Drop.” We utilize Drag and Drop without really giving it much thought – especially when its done right. Here are 5 easy steps to ensure an elegant implementation.

Defining drag and drop

A drag operation, essentially, is a click gesture on some UI element while the mouse button is held down and the mouse is moved. A drop operation occurs when the mouse button is released after a drag operation.

From a high level, drag and drop decisions can be summed up by the following flow chart.
Drag and drop decision flow chart.

To speed up our development, Ext JS provides us with the Ext.dd classes to manage the basic decisions for us. In this post, we will cover coding for the appearance and removal of the drop invitation, invalid drop repair and what happens when a successful drop occurs.

Organzing the drag and drop classes

A first glance of the classes in the Ext.dd documentation might seem a bit intimidating.  But, if we take a quick moment to look at the classes, we see that they all stem from the DragDrop class and most can be categorized into Drag or Drop groups.  With a bit more time and digging, we can see that the classes can be further categorized into single node and multiple node drag or drop interactions.

Ext JS Drag and drop class diagram.

In order to learn about the basics of drag and drop we’ll focus on applying single drag and drop interactions to DOM nodes.  To do this, we’ll utilize the DD and DDTarget classes, which provide the base implementations for their respective drag and drop behaviors.

However, we need to discuss what our objectives are before we can start implementing drag and drop.

The task at hand

Lets say we’ve been asked to develop an application that will provide a rental car company the ability to place their cars and trucks in one of three states:  available, rented or in repair status.  The cars and trucks are only allowed to be placed in their respective “available” container.

Drag and drop story.

To get started, we must make the cars and trucks “dragable”. For this, we’ll use DD. We’ll need to make the rented, repair and vehicle containers “drop targets”.  For this we’ll use DDTarget.  Lastly, we’ll use different drag drop groups to help enforce the requirement that cars and trucks can only be dropped into their respective “available” containers.

The HTML and CSS for this example is already constructed and can be downloaded here.  With that downloaded, we can begin coding by adding drag operations to the cars and trucks.

Step 1: Starting with drag

To configure the vehicle DIVs elements as dragable, we’ll need to obtain a list and loop through it to instantiate new instances of DD.  Here’s how we do it.

// Create an object that we'll use to implement and override drag behaviors a little later
var overrides = {};
// Configure the cars to be draggable
var carElements = Ext.get('cars').select('div');
Ext.each(carElements.elements, function(el) {
    var dd = new Ext.dd.DD(el, 'carsDDGroup', {
        isTarget  : false
    });
    //Apply the overrides object to the newly created instance of DD
    Ext.apply(dd, overrides);
});
 
var truckElements = Ext.get('trucks').select('div');
Ext.each(truckElements.elements, function(el) {
    var dd = new Ext.dd.DD(el, 'trucksDDGroup', {
        isTarget  : false
    });
    Ext.apply(dd, overrides);
});

All drag and drop classes are designed to be implemented by means of overriding its methods. That’s why in the above code segment, we have create an empty object called overrides, which will be filled in later with overrides specific to the action we need.

We get of list of car and truck elements by leveraging the DomQuery select method to query the cars container for all the child div elements.

To make the cars and truck elements dragable, we create a new instance of DD, passing in the car or truck element to be dragged and the drag drop group that it is to participate in. Notice that the vehicle types have their own respective drag drop group. This will be important to remember later when we setup the rented and repair containers as drop targets.

Also notice that we’re applying the overrides object to the newly created instances of DD using Ext.apply., which is a handy way to add properties or methods to an existing object.

Before we can continue with our implementation, we need to take a quick moment to analyze what happens when you drag an element on screen. With this understanding, the rest of the implementation will fall into place.

Peeking at how drag nodes are affected

The first thing you’ll notice when dragging the car or truck elements around is that they will stick wherever they are dropped. This is OK for now because we’ve just begun our implementation. What is important is to understand how the drag nodes are being affected. This will aid us in coding for the return to their original positions when they are dropped on anything that is a valid drop target, which is known as an “invalid drop”.

The below illustration uses FireBug’s HTML inspection panel and highlights the changes being made by when a drag operation is applied to the Camaro element.

Looking at how the drag operation changes the drag element's style
Click the above image to test the drag operation.

While inspecting the drag element during a drag operation, we can see a style attribute added to the element with three CSS values populated: position, top and left. Further inspection reveals that the position attribute set to relative and top and left attributes updating while the node is being dragged around.

After a the drag gesture completes, the style attribute remains along with the styles contained therein. This is what we have to clean up when we code for the repair of an invalid drop. Until we setup proper drop targets, all drop operations are considered invalid.

Step 2: Repairing an invalid drop

The path of least resistance is to repair an invalid drop by reseting the style attribute that is applied during the drag operation. This means that the drag element would disappear from under the mouse and reappear where it originated and would be quite boring. To make it smoother, we’ll use Ext.Fx to animate this action.

Remember that the drag and drop classes were designed to have methods overridden. To implement repair, we’ll need to override the b4StartDrag, onInvalidDrop and endDrag methods.

Lets add the following methods to our overrides object above and we’ll discuss what they are and do.

// Called the instance the element is dragged.
b4StartDrag : function() {
    // Cache the drag element
    if (!this.el) {
        this.el = Ext.get(this.getEl());
    }
 
    //Cache the original XY Coordinates of the element, we'll use this later.
    this.originalXY = this.el.getXY();
},
// Called when element is dropped not anything other than a dropzone with the same ddgroup
onInvalidDrop : function() {
    // Set a flag to invoke the animated repair
    this.invalidDrop = true;
},
// Called when the drag operation completes
endDrag : function() {
    // Invoke the animation if the invalidDrop flag is set to true
    if (this.invalidDrop === true) {
        // Remove the drop invitation
        this.el.removeClass('dropOK');
 
        // Create the animation configuration object
        var animCfgObj = {
            easing   : 'elasticOut',
            duration : 1,
            scope    : this,
            callback : function() {
                // Remove the position attribute
                this.el.dom.style.position = '';
            }
        };
 
        // Apply the repair animation
        this.el.moveTo(this.originalXY[0], this.originalXY[1], animCfgObj);
        delete this.invalidDrop;
    }
 
},

In the above code, we begin by overriding the b4StartDrag method, which is called the instant the drag element starts being dragged around screen and makes it an ideal place to cache the drag element and original XY coordinates – which we will use later on in this process.

Next, we override onInvalidDrop, which is is called when a drag node is dropped on anything other than a drop target that is participating in the same drag drop group. This override simply sets a local invalidDrop property to true, which will be used in the next method.

The last method we override is endDrag, which is called when the drag element is no longer being dragged around screen and the drag element is no longer being controlled by the mouse movements. This override will move the drag element back to its original X and Y position using animation. We configured the animation to use the elasticOut easing to provide a cool and fun bouncy effect at end of the animation.

Looking at how the drag repair operation works
Click the above image to view the animated repair operation in action.

OK, now we have the repair operation complete. In order for it to work on the drop invitation and valid drop operations, we need to setup the drop targets.

Step 3: Configuring the drop targets

Our requirements dictate that we will allow cars and trucks to be in be dropped in the rented and repair containers as well as their respective original containers. To do this, we’ll need to instantiate instances of the DDTarget class.

Here’s how its done.

//Instantiate instances of Ext.dd.DDTarget for the cars and trucks container
var carsDDTarget    = new Ext.dd.DDTarget('cars','carsDDGroup');
var trucksDDTarget = new Ext.dd.DDTarget('trucks', 'trucksDDGroup');
 
//Instantiate instnaces of DDTarget for the rented and repair drop target elements
var rentedDDTarget = new Ext.dd.DDTarget('rented', 'carsDDGroup');
var repairDDTarget = new Ext.dd.DDTarget('repair', 'carsDDGroup');
 
//Ensure that the rented and repair DDTargets will participate in the trucksDDGroup 
rentedDDTarget.addToGroup('trucksDDGroup');
repairDDTarget.addToGroup('trucksDDGroup');

In the above code snippet, we have setup drop targets for the cars, trucks, rented and repair elements. Notice that the cars container element only participates in the “carsDDGroup” and the trucks container element participates in the “trucksDDGroup”. This helps enforce the requirement that cars and trucks can only be dropped in their originating container.

Next, we instantiate instances DDTarget for the rented and repair elements. Initially, they are configured to only participate in the “carsDDGroup”. In order to allow them to participate in the “trucksDDGroup”, we have to add it by means of addToGroup.

OK, now we’ve configured our drop targets. Lets see what happens when we drop the cars or trucks on a valid drop element.

Click to see the partially completed drop operation in action.
Click the above image see the progress thus far.

In exercising the drop targets, we see that the drag element stays exactly its dropped. That is, images can be dropped anywhere on a drop target and stay there. This means that our drop implementation is not complete.

To complete it, we need to actually code for the “complete drop” operation, by means of another override for the instances of DD that we created some time ago.

Step 4: Completing the drop

To complete the drop, we will need to actually drag the element from its parent element to the drop target element using DOM tools. This is accomplished by overriding the DD onDragDrop method.

Add the following method to the overrides object.

// Called upon successful drop of an element on a DDTarget with the same
onDragDrop : function(evtObj, targetElId) {
    // Wrap the drop target element with Ext.Element
    var dropEl = Ext.get(targetElId);
 
    // Perform the node move only if the drag element's 
    // parent is not the same as the drop target
    if (this.el.dom.parentNode.id != targetElId) {
 
        // Move the element
        dropEl.appendChild(this.el);
 
        // Remove the drag invitation
        this.onDragOut(evtObj, targetElId);
 
        // Clear the styles
        this.el.dom.style.position ='';
        this.el.dom.style.top = '';
        this.el.dom.style.left = '';
    }
    else {
        // This was an invalid drop, initiate a repair
        this.onInvalidDrop();
    }

In the above override, the drag element is moved to the drop target element, but only if it is not the same as the drag element’s parent node. After the drag element is moved, the styles are cleared from it.

If the drop element is the same as the drag element’s parent, we ensure a repair operation occurs by calling this.onInvalidDrop.

Click to see the completed drop operation in action.
Click the above image to see the complete drop operation in action.

Upon a successful drop, the drag elements will now will be moved from their parent element to the drop target.

How does the user know if they are hovering above a valid drop target? We’ll give the user some visual feedback by configuring the drop invitation.

Step 5: Adding drop invitation

In order to make drag and drop a bit more useful, we need to provide feedback to the user on whether or not a drop operation can successfully occur. This means that we’ll have to override the onDragEnter and onDragOut methods

Add these last two methods to the overrides object.

// Only called when the drag element is dragged over the a drop target with the same ddgroup
onDragEnter : function(evtObj, targetElId) {
    // Colorize the drag target if the drag node's parent is not the same as the drop target
    if (targetElId != this.el.dom.parentNode.id) {
        this.el.addClass('dropOK');
    }
    else {
        // Remove the invitation
        this.onDragOut();
    }
},
// Only called when element is dragged out of a dropzone with the same ddgroup
onDragOut : function(evtObj, targetElId) {
    this.el.removeClass('dropOK');
}

In the above code, we override the onDragEnter and onDragOut methods, both of which are only utilized when the drag element is interacting with a drop target participating in the same drag drop group.

The onDragEnter method is only called when the mouse cursor first intersects the boundaries of a drop target while a drag item is in drag mode. Likewise, onDragOut is called when the mouse cursor is first dragged outside the boundaries of the drop target while in drag mode.

Click to see the drop invitation.
Click the above image to see the drop invitation.

By adding overrides to the onDragEnter and onDragOut methods we can see that the background of the drag element will turn green when the mouse cursor first intersects a valid drop target and will lose its green background when it leaves the drop target or is dropped. This completes our implementation of drag and drop with DOM elements.

It doesn’t stop here

Drag and drop can be a can be applied to mostly everything in the Ext JS framework. Here are a few examples that you can use to learn how to implement drag and drop with various widgets:

Summary

Today, we learned how to implement end to end drag and drop of DOM nodes using the first-level drag and drop implementation classes. From a high-level, we defined and discussed what drag and drop is and how to think about it in terms of the framework.

We also learned that the drag and drop classes can be grouped by drag or drop behaviors and whether or not they support single or multiple drag or drop operations. While implementing this behavior, we illustrated that the dd classes help make some of the behavioral decisions, and that we are responsible for coding the end-behaviors.

We hope you’ve enjoyed this thorough look at some fundamental drag and drop operations with DOM nodes. We look forward to bringing you more articles about this topic in the future.

Building a Rating Widget with Ext Core 3.0 Final and Google CDN

Wednesday, June 10th, 2009

We are very proud to announce the final release of Ext Core under the MIT license. Your feedback was invaluable. Thank you for all the bugs reported and test cases created. For those of you who are new to Ext Core, we suggest you read the previous blog post about the all the features and examples that we released as part of the beta. You can find a list of changes and fixes we made for the final here.

For this post we will leverage the power of Ext by creating and dissecting a useful star rating example. We hope to share some of the general best practices behind creating unobtrusive, reusable code with Ext Core to liven up your pages.

Making a Splash

Including Ext Core on your site is easier than ever. We are honored to share with the community that Ext Core is now available via the Google AJAX Library API. Many thanks to Ben Lisbakken at Google for working with us to make this a reality.
//any of these will work ;)  <script type="text/javascript" src="....
http://ajax.googleapis.com/ajax/libs/ext-core/3.0/ext-core.js
http://ajax.googleapis.com/ajax/libs/ext-core/3/ext-core.js
http://ajax.googleapis.com/ajax/libs/ext-core/3.0/ext-core-debug.js
http://ajax.googleapis.com/ajax/libs/ext-core/3/ext-core-debug.js
Alternatively, you can use Google AJAX API Loader's google.load() method:
google.load('ext-core', '3');
google.load('ext-core', '3', {uncompressed : true});

Getting Started

Ext Core is a perfect fit for adding behavior to existing HTML. When designing a widget, having a markup structure that provides graceful degradation is an added plus. For this example, we will be using radio buttons. We can "group" the elements to specify which radio buttons are part of the control. It could look something like the following:
<div id="rating1">
    <input type="radio" name="rating1" value="1" title="Very poor">
    <input type="radio" name="rating1" value="2" title="Not that bad">
    <input type="radio" name="rating1" value="3" title="Average">
    <input type="radio" name="rating1" value="4" title="Good">
    <input type="radio" name="rating1" value="5" title="Perfect">
</div>
This markup allows user to have the ability to rate an item even without the fancy stars and additional functionality that we have in mind. Take notice that this simple markup contains powerful information like the name, value and title for each item which we can reuse with our rating widget.

The API

One of the most important aspects of building reusable code is providing your developers a powerful API. Our aim here is to allow developers to progressively enhance and convert the markup into a star rating with a simple API. In this case we will need the element that wraps around the radio controls, and some optional configuration to customize the behavior of the widget. Following the Ext tradition we will provide these configuration options in the form of an object literal. A possible API for our widget could look like this:
//Keep it simple
new Ext.ux.Rating('rating1', {
    showTitles: true
});

Ext.util.Observable

So now that we know how we want to use our component, lets go ahead and actually look at some details on how to write it! In our previous post we mentioned that Ext Core allows you to write neatly structured object-oriented code. Whenever you want to create a piece of functionality, you should try to bundle it into a separate class. In most cases you will need to be able to listen for events on instances of your class. Ext provides a power class, the Ext.util.Observable class, to springboard your development. This is the same class that almost all classes in Ext JS extend from! Our basic shell for our rating plugin could look something like this:
Ext.ns('Ext.ux');
Ext.ux.Rating = Ext.extend(Ext.util.Observable, {
    // Configuration default options
    showTitles: true,
 
    // Our class constructor
    constructor : function(element, config) {
        Ext.apply(this, config);      
        Ext.ux.Rating.superclass.constructor.call(this);     
 
        this.addEvents( 'change');  
 
        this.el = Ext.get(element);
        this.init()
    }
});
For those of you familiar with Ext JS will recognize this pattern. In this piece of code we have created a namespace to put our class into using the Ext.ns() function. Then we create our class using the Ext.extend method with Ext.util.Observable as the base class. We define some configuration options with default values and then set up our constructor method which will be called when we create a new instance of our class. We also define some custom events and wrap the element passed to the constructor with an Ext.Element instance. We use the Ext.get() flexible nature to have support of passing an id string, DOM Element or Ext.Element to our constructor.

Reaching the stars

It is time to think about the things we need to get our widget working. First we want to replace the radio buttons with our stars, we will need to store the values and titles for each star, we want to create a hidden input to put the current value in and finally we need to set up event listeners to listen for mouse hovers and clicks.
init : function() {
    var me = this; 
 
    // Some arrays we are going to store data in
    this.values = [];
    this.titles = [];
    this.stars = [];
 
    // We create a container to put all our stars into
    this.container = this.el.createChild({
        cls: 'ux-rating-container ux-rating-clearfix'
    });
 
    // We use DomQuery to select the radio buttons
    // Then we can loop over the CompositeElement using each
    this.radioBoxes = this.el.select('input[type=radio]');
    this.radioBoxes.each(this.initStar, this);
 
    // We use DomHelper to create our hidden input
    this.input = this.el.createChild({
        tag: 'input',
        type: 'hidden',
        name: this.name,
        value: this.values[this.defaultSelected]
    });
 
    // Lets remove all the radio buttons from the DOM
    this.radioBoxes.remove();
 
    if(this.disabled) {
        this.disable();
    } else {
        // Enable will set up our event listeners
        this.enable();
    }
}

Creating Stars - using DomHelper and accessing the DOM from Ext Element

 
initStar : function(item, all, i) {
    // We use the name and disabled attributes of the first radio button 
    if(i == 0) {
        this.name = item.dom.name;
        this.disabled = item.dom.disabled;		
    }
 
    // Saving the value and title for this star     
    this.values[i] = item.dom.value;
    this.titles[i] = item.dom.title;
 
    // Now actually create the star!
    var star = this.container.createChild({
        cls: 'ux-rating-star'
    });
 
    // Save the reference to this star so we can easily access it later
    this.stars.push(star.dom);
},

Enable and Select Stars - listening for events, using the target of an event and firing custom events

 
enable : function() {
    // ... some code missing here ...
 
    // We will be using the technique of event delegation by listening
    // for bubbled up events on the container       
    this.container.on({
        click: this.onStarClick, 
        mouseover: this.onStarOver,
        mouseout: this.onStarOut,
        scope: this,
        delegate: 'div.ux-rating-star'
    });        
},
 
onStarClick : function(ev, t) {
    if(!this.disabled) {
        this.select(this.stars.indexOf(t));
    }
},
 
select : function(index) {
    // ... some code missing here ...
    else if(index !== this.selected) {
        // Update some properties           
        this.selected = index;
        this.value = this.values[index];
        this.title = this.titles[index];
 
        // Set the value of our hidden input so the rating can be submitted			
        this.input.dom.value = this.value;
 
        // the fillTo() method will fill the stars up until the selected one
        this.fillTo(index, false);
 
        // Lets also not forget to fire our custom event!         
        this.fireEvent('change', this, this.values[index], this.stars[index]);  
}

Filler Up - dom manipulation (adding classes)

 
fillTo : function(index) {
    var cls = 'ux-rating-star-on';
 
    // We add a css class to each star up until the selected one   
    Ext.each(this.stars.slice(0, index+1), function() {
        Ext.fly(this).addClass(cls);
    });
 
    // And then remove the same class from all the stars after this one
    Ext.each(this.stars.slice(index), function() {
        Ext.fly(this).removeClass(cls);
    });      
}

We won't discuss all the details since most of it is pretty straightforward, but the final product should give you a general idea of how to use the basic functionality available in Ext Core to tie together all the missing pieces.

Wrapping it up

In this example we used the following cross-browser compatible functionality available in Ext core:
  • Classical Inheritance Class System
  • Observable Class
  • DomQuery
  • DOM manipulation and traversal
  • Event handling
  • Markup generation

Ext Core makes it fun to write code, and helps you create clean, well-structured classes using a set of cross-browser abstractions on the existing browser API's. For those of you who want to use it or are just interested in seeing the completed work, we have included a version of the widget in the Ext Core Final build. You can see the working widget embedded in the post below:

The example page illustrating this widget can be found here.

Final words

We hope that this library will find its way into many of your dynamic web pages and make your lives as web developers easier and more enjoyable. We are looking forward to seeing the great things you will create using it. We are always looking for ways to make this library better and we think the best way to do that is by listening to your suggestions. So, don't be shy and tell us what you think.

Ext JS Books: Resources to Master the Framework

Monday, March 16th, 2009

Learning an exciting software framework can be like climbing a mountain — it requires proper equipment, technical skill and determination. To help new and seasoned community members reach the Ext apex, three new books have come to our attention to help guide your path.

Ext JS in Action

Author: Jesus D. Garcia, Jr.
Discount code: extjs40 (40% off until April 1)
Description:

  • Part 1: Introduction to Ext JS

    • A framework apart
    • An Ext JS primer
    • A place for components
    • Organizing components
  • Part 2: Ext components

    • Building a dynamic form
    • The venerable Ext DataGrid
    • Taking root with Ext Trees
    • Toolbars and menus
    • Advanced element management
    • The Ext toolbox
    • Drag and drop
  • Part 3: Building a configurable composite component

    • Developing object-oriented code with Ext
    • Building a composite widget
    • Applying advance UI techniques
 

The author, Jesus Garcia is a long-time member of the Ext JS forums with a well-documented history of helping others in his 7600+ posts. His book, Ext JS In Action, will make an excellent companion to Learning Ext JS below, since it takes a more-technical bottom-up approach to teaching Ext JS. Mr. Garcia demonstrates a thorough understanding of low-level DOM manipulation and event-handling, including the differences between browsers.

The book contains many excellent diagrams primed for printing and posting beside your monitor, like the following illustration of the Ext class hierarchy depicting common descendants of Ext.Component:

Though still in development, this excellent book for both Ext JS new-comers and advanced developers alike is currently available through the Manning Early Access Program. Says Steven Hong of Manning Publications:

“I’ve taken the liberty of setting up a discount code for your readers to use. Until April 1, your readers can use the code extjs40 at www.manning/garcia to receive 40% off the retail value of the book”

We at Ext JS thank Manning Publications for their generous offer to our community.

Learning Ext JS

Authors: Shea Frederick, Colin Ramsay, Steve “Cutter” Blades
Description:

  • Chapter 1 introduces you to the process of installing the required Ext JS library files, and setting up a basic page that displays an alert-style message. This provides us with a way to test whether your setup was done correctly, and whether you’re ready to play with some code. We also cover how to set up other base libraries such as jQuery, YUI, and Prototype, to work in conjunction with Ext JS.
  • Chapter 2 covers how to interact with the web page and the user. With example code that uses simple components, we quickly start to see the level of user interactivity that Ext JS provides right out of the box. We assemble a series of dialogs that appear and modify the existing pages depending upon the users’ inputs.
  • Chapter 3 launches us into using the first major widget—forms. We start by creating a simple form with three fields, explore the different form field types, and then add some simple validation to our form. From there we move on to creating custom validation and database-driven combo-box’es and handling form submissions.
  • Chapter 4 provides an overview of how to use toolbars and buttons within your
    application. These components are typically undervalued, yet they provide crucial user interface functions. We jump straight into creating toolbars with buttons, split buttons, and menus, along with adding mechanical elements such as spacers and dividers. Next, we cover customizing the toolbar with stylized icon buttons and form fields.
  • Chapter 5 covers grids—the most widely-utilized component in the Ext JS library. In
    this chapter, we learn how to set up a grid panel using both local and remote data, and in both in XML and JSON formats. We also discuss how to prepare different data types and how to create renderers that will style and format the data to your preference. Using the selection model and paging are among the many interesting points covered in this chapter.
  • Chapter 6 dives into editor grids. Here, we learn how to set up an editor grid using
    different form field types, and how to save changes made in the grid back to the server or database. We also discuss tactics for adding and removing rows of data to and from our data store, and the server or the database.
  • Chapter 7 explores the concept of using the layout component to bring all the portions of your application together into a cohesive web application. We start by using a viewport with a border layout to contain the many parts of our application. From there we are able to add other layout features such as tab panels, accordions, and toolbars. We finish up by learning how to nest layouts and make dynamic changes to the layout components.
  • Chapter 8 discusses the presentation of hierarchical information using the Ext JS Tree support. Using real-world examples of hierarchical data, you will discover how to display and manipulate a Tree view. You will use AJAX techniques to persist the modifications to a server and learn how to tweak the Tree to support advanced scenarios.
  • Chapter 9 demonstrates how Ext JS can provide attractive user prompts that can either present information or accept input. We then discuss the extension of these dialogs in the form of Ext.Window, a fully-fledged means of creating customizable pop-up windows.
  • In Chapter 10, we take a tour of the visual effects available in the Ext JS effects package. You will learn how to apply animations to create smooth transitions and notifications to enhance the user experience.

Well-written and well-produced, Learning Ext JS takes a top-down approach to teaching Ext JS, which might be daunting for those having little experience with the framework. However, this approach will certainly immerse the reader quickly into a number of common techniques used througout the framework, like XType, configuration objects and common component configuration parameters.

After starting off with an excellent tutorial on how to download and include the library’s JavaScript & CSS assets, the authors quickly jump full-force into Ext forms in the third chapter and beyond, guiding the reader through all of Ext’s high-level widgets using an evolving “movie database” application with server-side code examples in both php and ColdFusion.

var store = new Ext.data.GroupingStore({
  url: 'movies.json',
  sortInfo: {
    field: 'genre',
    direction: "ASC"
  },
  groupField: 'genre',
  reader: new Ext.data.JsonReader({
    root:'rows',
    id:'id'
  },fields);
});
var grid = new Ext.grid.GridPanel({
  renderTo: document.body,
  frame:true,
  title: 'Movie Database',
  height:400,
  width:520,
  store: store,
  autoExpandColumn: 'title',
  columns: // column model goes here //,
  view: new Ext.grid.GroupingView()
});

In the final chapters, the authors provide some excellent material in more advanced topics, like Ext’s data package, extending Ext core classes with Ext.extend, overriding initComponent & onRender in your extensions and organizing your extensions into separate files. If you’ve already got experience with Ext JS, this book will do wonders in focusing your skills.

Ext JS Projects with Gears

Author: Frank Zammetti
Description (by the author)

  • Nine chapters in total. The first is your typical “Intro to Ext JS”. I start with a few pages on RIA development, the evolution of web development in general, etc. I talk about how there’s now a lot of choices in toolkits and of course wind up saying that Ext JS is the best of the bunch IMO I then quickly give a basic first application with Ext JS (not much more than “hello world”). Then it’s on to some details… things like Ext JS’s overall structure, the stuff added to intrinsic classes, then the stuff directly under the Ext namespace. I then go into Ext.util in some detail.
  • Chapter 2 is the more “advanced” introduction… I cover the inheritance model behind widgets, the basics of widget usage, then details about the concept of layout and layout managers. I then cover most of the core widgets in some detail. I also talk about the data subsystem, templating capabilities, drag-and-drop and state management. I also talk a bit about plugins and some of the great user extensions out there. This chapter also introduces Gears, which although the lesser player in the game is a big part of the chapters to follow.
  • Chapters 3-9 are the project chapters. Each of them presents a sovereign, unique, full application using Ext and Gears. This is the meat of the book (the “practical projects”!). The idea here is learn-by-example (and learn-by-doing because the end of each chapter presents suggested exercises to the reader).

In the Ext forum-post where Mr. Zammetti introduced Ext JS With Gears, he stresses:

“Keep in mind that this book is in no way trying to be an exhaustive, detailed look at Ext… I purposely had to leave some things out, but I tried my best to cover everything that I thought was most relevant to a modern web developer.”

Frank Zammetti is a prolific writer at Apress, authoring five books there so far.

extjs.com

Those new to Ext JS should be aware of a number of important learning resources within extjs.com itself, where you’ll find material on gathering the right equipment along with lessons and tutorials to hone your skills, from javascript fundamentals to advanced techniques.

Ext API Docs

Like a GPS device for the framework, the Ext API docs have always been of superior quality and are one of the primary reasons for the framework’s success. You can find the docs online at www.extjs.com/docs, in your locally downloaded copy of the library (eg: ext-2.2/docs) or as a downloadable Adobe Air application.

The Ext Forum

The Ext forum is a large, diverse community with over 60000 registered users (as much as a small city!), including a couple of heavy-weights with over 10000 posts. These guys have seen it all and know what they’re talking about (some of you might recognize the fourth character in this list, Mr. jgarcia, the author of Ext JS In Action above.)

Ext Forum Top-posts

Whichever server-side technologies you’re bringing with you into Ext — .NET, Merb/Ruby on Rails, Enterprise Java or PHP — you’ll find someone in the Ext Forum who’s already been down the road you’re on, so register now—it’s free.

Community Learning Center

Available through the Support tab on our website, the Ext JS Community Learning Center contains an evolving collection of training resources that will accelerate your transition into Ext JS, including the Ext JS Manual, interactive demos, tutorials, screencasts and much more.

Ext Enterprise Training

We love to travel and we love to teach. From beginning JavaScript and CSS to custom component creation and CSS theming, your team will learn how to bring it all together to create innovative web user interfaces with hands-on training by a member of the Ext Core Development Team.

Ext Conference 2009

This April, join Jack and the Core Development Team as we host the 1st Annual Ext Conference and Ext 3.0 release party. Connect with other members of the Ext Community while learning about Ext 3.0′ s innovative features.

Tools, Black-belts & Meetups

Jozef Sakalos, aka Saki

One of the top Ext experts in the world as well as a member of the Ext Support Team, Saki maintains an Ext Examples Page as well as an active blog.

The User-extension Repository

The User-extension repository is an attempt to build a centralized database of API documentation for 3rd-party ux (user-extension) components using the familiar Ext documentation style.

Meetups

Both Jay Garcia (author of Ext JS in Action) and Shea Frederick (an author of Learning Ext JS) have been partaking in the Baltimore/DC JavaScript UserGroup Peter Kellner has also organized the San Francisco Ext JS UserGroup. I gave a presentation last week on the innovative new features Ext 3.0 to the S.F. Ext JS Group via a webex.

Conclusion

As the Ext framework matures, the community surrounding it is also maturing. We are seeing several excellent resources for learning Ext sprout up and an extremely active blogosphere discussing how people are using Ext in their day to day projects. If you regularly blog about Ext, please let us know we’d like to follow you on your journey in discovering Ext. Start a meetup in your area and connect with other members of the community who are building applications on the Ext platform.

Testing Ext JS & Ext GWT Applications With Selenium

Monday, November 3rd, 2008

Overview

As developers we can create great software. Unfortunately, we usually introduce a few bugs along the way. Using a testing tool can ensure we catch the bugs and resolve them quickly.

There are many different approaches to testing. Some advocate writing the tests within the application, others suggest a separate testing environment entirely. There are merits to both these approaches. For this blog post, I’ve focused our attention on Selenium as both Ext JS and Ext GWT and benifit from this “black box” testing methodology.

Selenium provides a powerful mechanism to test your Ext applications. Selenium works by executing tests against your running application within the browser of your choice. Selenium tests emulate the way a user would interact with your application by executing JavaScript to simulate user actions. Selenium tests run as a form of “integration” tests as they execute against your running application.

Both Ext JS and Ext GWT applications can benefit from Selenium tests. In fact, with few exceptions, the tests created for one product should be interchangeable as both products produce the same DOM structure.

With GXT applications, GWT provides built in JUnit support. This provides a great way to test your application. However, these tests run only in host mode. Being able to test your compiled application in multiple browsers is important as some issues only appear within your compiled application.

In general, you create Selenium tests and then execute them in a variety of ways. This tutorial will demonstrate creating tests with Selenium IDE, a Firefox plugin, and creating tests within Java. Tests will be loaded and executed within the Selenium IDE, and Java JUnit tests will be executed using Selenium Remote Control.

Selenium IDE

Selenium IDE is a Firefox extension that allows you to create, edit, and execute your tests. Tests can either be created manually, or by “recording” your actions. Recording can help you get a feel on how the Selenium commands are generated, but in most cases you will want to tweak the generated commands.

A Selenium test is a list of commands. Commands can be seen as actions, such as “click this element”, “type into this field”, and “assert an element exists”.

Install Selenium IDE

First, you will need to install the plugin which can be found here. Once installed you can choose Tools / Selenium IDE or View / Sidebar / Selenium IDE from the Firefox application menu.

Spend some time playing around with Selenium IDE. You can use the record button (red circle) to have the tool record your actions or you can enter commands manually. Most commands require a locator string. The locater string is repsonsible for identifying elements. There are various “types” of locator strings which are covered later.

Using Selenium IDE you can save and load tests. Also, notice the source tab. This tab allows you to view the test source. Selenium tests are saved as HTML files and can be exported to multiple server-side languages PHP, Ruby, Java, C#, Perl, and Python.

Creating a new Selenium Test

In this example, we will be testing both an Ext JS and Ext GWT form and it’s fields. First, let us take a look at the example code we will be testing. You can find the source code here:

Rather than creating a test from scratch, we will load an existing test file (listed above). Download this either the Ext JS or Ext GWT file to your file system. Then open the test in the Selenium IDE by selecting File / Open. Once loaded, Selenium IDE should look this this:

Notice the list of commands. Take a look at each command to get a feel of what the test is doing. If you opened Selenium IDE as seperate window, close it. Then open Selenium IDE using View / Sidebar / Selenium IDE. This will place selenium in the sidebar making it easier to run and monitor tests.

You can execute the test by clicking the first icon with the green arrow in the tool bar. Notice that you can control execution speed, use break points, execute individual commands, etc. After running your test, you screen should look like this:

Notice the form fields have been filled out. Examine the commands closely to see what actions were taken and what assertions where made. This test only touches the surface of things you can accomplish with commands. Note: When running the Ext JS test file, the radios and check boxes will not show the checked state, however, the true state will be correct, and the tests will run successfully.

Selenium Locators

Many Selenium commands require a locator to be specified. A locator is a way to identify an element in the page (the DOM to be specific). There are various types of locators including id, name, dom, xpath, link, and css. For this tutorial, XPath expressions where used. XPath expressions provide a powerful mechanism to identify elements. Example expressions look like this:

//input[@name='name']
//input[@name='name' and contains(@class, 'x-form-invalid')]
//input[@name='company']/following-sibling::img
//div[@id='Apple']
//div[@class='x-combo-list-item'][3]

Here are a few examples using CSS selectors:

css=html:root
css=div#structuralPseudo :nth-last-child(2)
css=a[class~="class2"]

Executing Tests with Selenium Remote Control (RC)

Selenium IDE provides a great way to create your tests and execute them in Firefox. Tests can only be run by manually opening Firefox and executing tests. What if you want to run you want to automate your tests and run them in other browsers? This is where Selenium Remote Control comes into play.

From the Selenium website: "Selenium Remote Control (RC) is a test tool that allows you to write automated web application UI tests in any programming language against any HTTP website using any mainstream JavaScript-enabled browser. Selenium RC comes in two parts. 1. A server which automatically launches and kills browsers, and acts as a HTTP proxy for web requests from them. 2. Client libraries for your favorite computer language."

Download Selenium RC

In addition to Selenium IDE, Selenium RC must be downloaded and can be found here. After downloading, unzip the file to your file system.

Starting the Server

The first step in using Selenium is to start the server. The server is responsible for executing your tests. The server will open browser instances, run tests, and close browsers. The server is written in Java and can be started by executing this command:

java -jar selenium-server.jar

The command should be executed from the folder where the selenium-server.jar is located.

To run your tests in Java, you must reference the Java client library. See selenium-java-client-driver.jar in the Selenium RC download.

Creating a test in Java

Selenium RC supports various languages, we will focus on Java. Rather than creating the Java test from scratch, Selenium IDE can be used to create the base Java code needed to create the test. From Selenium IDE, select the source tab, then choose Options / Format / Java. You will see the test is converted form HTML to Java. You can then copy and past the Java code to be used in your Java test. You can use the same steps to create code in other languages such as PHP and Ruby.

Here is the Java code that was created using the template code from Selenium IDE:

public class SeleniumTestCase extends SeleneseTestCase  {
 
  private Selenium selenium;
 
  public void setUp() {
    selenium = new DefaultSelenium("localhost", 4444, "*iexplore", "http://extjs.com");
    selenium.start();
  }
 
  public void testForm() {
    selenium.open("http://extjs.com/playpen/gxt/selenium/");
    pause(500);
    selenium.type("//input[@name='name']", "John");
    selenium.fireEvent("//input[@name='name']", "blur");
    assertTrue(selenium.isElementPresent("//input[@name='name' and contains(@class, 'x-form-invalid')]"));
    selenium.type("//input[@name='name']", "Darrell");
    selenium.fireEvent("//input[@name='name']", "blur");
    assertFalse(selenium.isElementPresent("//input[@name='name' and contains(@class, 'x-form-invalid')]"));
    selenium.type("//input[@name='email']", "darrell@foo.com");
    assertEquals("Darrell", selenium.getValue("//input[@name='name']"));
    assertEquals("darrell@foo.com", selenium.getValue("//input[@name='email']"));
    selenium.focus("//input[@name='company']");
    selenium.click("//input[@name='company']/following-sibling::img");
    assertEquals("43", selenium.getXpathCount("//div[@class='x-combo-list-item']"));
    selenium.click("//div[@id='Apple']");
    assertEquals("Apple Inc.", selenium.getValue("//input[@name='company']"));
    selenium.click("//input[@name='birthday']/following-sibling::img");
    selenium.click("//button[contains(text(), \"Today\")]");
    assertTrue(selenium.getValue("//input[@name='birthday']").matches("^[\\s\\S]*$"));
    selenium.check("//input[@value='Classical']");
    assertEquals("on", selenium.getValue("//input[@value='Classical']"));
    selenium.check("//input[@value='Blue']");
    assertEquals("on", selenium.getValue("//input[@value='Blue']"));
  }
 
  public void tearDown() {
    selenium.stop();
  }
 
}

Notice the use of "pause" after opening the application. This is needed to allow the GWT application to load. Other than that, the test code is a direct paste from the code generated in Selenium IDE. Notice that the test is using "*explorer" to execute the test. Firefox, Opera, Safari, Chrome are also supported. Keep in mind that the browser must be installed on the same maching where the Selnium server is running.

The new JUnit test can be executed just like any other JUnit test. The test can be executed with Eclipse.

Selenium Grid

Although it is not used in the tutorial, Selenium Grid is worth mentioning. From the website: "Based on the excellent Selenium web testing tool, Selenium Grid allows you to run multiple instances of Selenium Remote Control in parallel. Even better, it makes all these Selenium Remote Controls appear as a single one, so your tests do not have to worry about the actual infrastructure. Selenium Grid cuts down on the time required to run a Selenium test suite to a fraction of the time that a single instance of Selenium instance would take to run."

Summary

The tutorial demonstrated how load and run tests within Selenium IDE. The test code was ported to Java where it was run using Selenium Remote Control in a JUnit. This tutorial demonstrated the major moving parts involved in Selenium tests. It is recommended to take a look at the Selenium documentation and tutorials for more information.

Many thanks go out to the Selenium Team. There is a slight learning curve getting familiar with the product but I found it straightforward. The time was well spent as it opens up a new approach to testing web applications.

Preview: Java Bean support with Ext GWT

Monday, July 14th, 2008

The Ext GWT Store and Binder API work with ModelData instances. The primary goal of ModelData is to provide a type of “introspection” as GWT does not allow runtime inspection of Java objects. You can query ModelData for a list of properties it contains, and these properties can be retrieved and set using the parameter name with the get and set methods.

Although this approach works, it forces you to either implement the ModelData interface in your Java Beans or extend the Ext GWT base classes that implement the ModelData interface. What is missing is a way to use your Java Beans as is, without having to extend the Ext GWT base classes or implement an “invasive” interface.

With the 1.1 release of Ext GWT, it is possible to use any Java Beans in the Store and Binder API. This allows you to send your Java Beans from server to client using GWT RPC.

Java Bean support is provided by dynamically creating new BeanModel instances using any bean. The new type will “wrap” the bean, and all get and set calls on the model will be delegated to the underlying bean. Also, the original bean is available via the new bean model instance. The new model instances are created using a GWT Generator. Basically, the generator allows “new” types to be created at compile time using GWT.create(). The GXT generator will create a BeanModelFactory than can create new BeanModel instances from a Java Bean.

Identifying Java Beans

There are 2 ways of identifying Java Beans. The first method requires a new interface that extends BeanModelMarker and uses annotations. This method does not require the JavaBean to be modified. With the second method, your Java Bean implements the BeanModelTag interface.

BeanModellMarker Interface

The first step to enable Java Bean support is to identify the Class you would like to “adapt”. Rather than specifying the class directly, a new interface is created that extends BeanModelMarker. Then, a @BEAN annotation is added to the interface to identify the actual bean. This approach is beneficial, as it allows a single deferred binding rule to be used to identify your bean. Also, by using a marker interface, other configuration information can be specified by annotations.

public class Customer implements Serializable {
 
  private String name;
  private int age;
 
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
 
}
 
@BEAN(Customer.class)
public interface CustomerBeanModel extends BeanModelMarker {
 
}

BeanModelTag Interface

With this method, a new interface is not required as you tag the Java Bean directly. This means your beans will have a reference to a GXT interface.

public class Customer implements BeanModelTag, Serializable {
 
  private String name;
  private int age;
 
  public int getAge() {
    return age;
  }
 
  public void setAge(int age) {
    this.age = age;
  }
 
  public String getName() {
    return name;
  }
 
  public void setName(String name) {
    this.name = name;
  }
}

BeanModelLookup

BeanModelLookup is used to obtain a BeanModelFactory instance for a given bean type. You will use the BeanModelLookup singleton to obtain a BeanModelFactory for your given bean. The BeanModelFactory can be used to create new bean model instances from your bean instances.

BeanModelFactory factory = BeanModelLookup.get().getFactory(Customer.class);

With the factory, you are able to create new BeanModel instances that wrap your bean.

Customer c = new Customer();
c.setName("Darrell");
BeanModel model = factory.createModel(c);

BeanModelReader

It is common to use the GXT data loading API to retrieve remote data and populate a Store. The BeanModelReader can be used to handle creating new model instances from the beans being returned from the data proxy. With this approach, you can return any Java Beans from the RPC call. BeanModelReader will lookup the factory given the type of the objects being returned from the data proxy.

Store

When using this approach, the type of objects in the store will be the dynamically created types that were created based on the bean. These objects will extend BeanModel. BeanModel provides access to the “wrapped” bean via the getBean method.

Customer customer = (Customer)model.getBean();

Grid Example

Here is a snippet of code from the Explorer demo. It demonstrates uses a BeanModelReader with a Grid.

    // gwt service
    final ExplorerServiceAsync service = (ExplorerServiceAsync) Registry.get("service");
 
    // proxy and reader
    RpcProxy proxy = new RpcProxy() {
      @Override
      public void load(Object loadConfig, AsyncCallback callback) {
        service.getCustomers(callback);
      }
    };
    BeanModelReader reader = new BeanModelReader();
 
    // loader and store
    ListLoader loader = new BaseListLoader(proxy, reader);
    ListStore<BeanModel> store = new ListStore<BeanModel>(loader);
 
    loader.load();
 
    // column model
    List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
    columns.add(new ColumnConfig("name", "Name", 200));
    columns.add(new ColumnConfig("email", "Email", 100));
    columns.add(new ColumnConfig("age", "Age", 50));
    ColumnModel cm = new ColumnModel(columns);
 
    Grid<BeanModel> grid = new Grid<BeanModel>(store, cm);
    grid.setAutoExpandColumn("name");
    grid.setWidth(400);
    grid.setAutoHeight(true);
    grid.setBorders(true);

Summary

The new Java Bean support allows easy data integration of your existing Java Bean objects. Sending any Java Bean over the wire is possible, and Ext GWT can create bean model instances on the client.

These features will be available with the 1.1 release of Ext GWT. For those with access to SVN, the working code is in the trunk.

Learning Ext: Many Resources Available

Tuesday, March 11th, 2008

The Ext JavaScript library is a robust framework encompassing components for many typical development needs. With support for DOM traversal/manipulation, UI controls, data binding and more, Ext provides the hooks and tools to help build engaging applications.

We’re frequently asked about online resources that can help developers become more proficient with Ext. There’s a wealth of information provided on the Ext Learning Center section of our website that can be extremely effective in helping Ext developers become more proficient in the framework.

Hosted Tutorials

The Ext Learning Center is one of the best places to get material to learn about Ext. The tutorials cater to both new and experienced Ext developers and cover a broad range of topics including application design, DOM manipulation using DomQuery, Drag and Drop and Grid implementation to name of few. If you’re new to Ext, you definitely want to start off with the Introduction to Ext 2.0 tutorial. It’s an excellent starting point which highlights the usage of some very important features and helps to build the foundation for you to work from.

Advanced developers can take advantage of other tutorials such as Extending an Ext Class or Writing Ext 2 Plugins. These tutorials, along with several others, are clearly geared towards advanced Ext developers and are designated as such.

“In the Wild” Ext Tutorials

A number of developers have created some great tutorials and examples on their personal sites. Here are just a few tutorials found via Google which cover a variety of topics and development platforms:

Again, this is only a small subset of the numerous Ext JS postings that can be found via Google. Remember, Google is your friend. :)

Ext Sample Applications

One of the best ways to get familiar with Ext best practices is by reviewing code from quality applications. The Ext demo applications, conveniently found on the Ext homepage, are excellent examples of how to use a wide variety of Ext’s powerful functionality. The applications are included in the downloadable version of the Ext JS framework and are an excellent resource for improving your Ext skills.

Ext Onsite Training

If you really want to have a more personal experience, then Ext’s onsite training service is a great solution to get your team ramped up. Conducted by a Ext Core Team member, the onsite training class offers a hands-on, instructor-led environment where developers can learn from an expert. This is by far the best method of getting familiar with Ext as it’s 2 days of intensive training in the core areas of the Ext framework coupled with the ability to get immediate feedback from an instructor. If you’re interested in having an onsite training class, please visit the Ext Training page for more details about the class.

Many Options to Choose From

Providing information to help Ext developers refine their skills is extremely important to the team and hopefully, you’ll now have more resources at your disposal. We will continue to add more resources, both Ext-driven and community-submitted, to the site to help developers build top-notch applications.