2010: The year Ext JS takes over
January 13, 2010 by Ed Spencer · 18 Comments
On January 1st 2010 I officially joined Ext JS to take over the role of lead developer. After living and breathing Ext for the last 3 years I am delighted to have joined the company itself. Ext JS has lead the way in developing rich client side applications since the very first release; this is a tradition we will continue and build upon.
2010 is going to be an extremely exciting year for Ext JS. A new focus is being placed on helping developers create their applications much more quickly, with the help of advanced creation tools and a standardised application architecture right out of the box.
We will continue the performance improvements started in 3.1 to make sure that Ext applications really fly. Ext JS 3.2 will be the fastest, most stable version ever released.
2010 is also the year that Ext JS becomes much easier to learn. With a completely reinvented learning section, Ext will no longer take months to learn and understand – even our API documentation will get a facelift.
The upcoming Marketplace will be the perfect venue to find and share new, high quality components created by our awesome developer community. Think of the Marketplace as the App Store for Ext JS – full of great offerings that are easy to drop in to any application.
Calling all able-minded Ext JS developers
Ext JS is already the best JavaScript library in the world for creating rich, desktop-quality applications on the web. If you want to help us make it even better, I want to hear from you.
As well as creating new components and improving our application support, we need people to help us maintain the quality and stability of what we already have. If you’re intimate with Ext and think you have what it takes to get involved, drop me a PM and introduce yourself.
Ext.ux.Exporter – export any Grid to Excel or CSV
November 24, 2009 by Ed Spencer · 15 Comments
Sometimes we want to print things, like grids or trees. The Ext JS printing plugin is pretty good for that. But what if we want to export them instead? Enter Ext.ux.Exporter.
Ext.ux.Exporter allows any store-based component (such as grids) to be exported, locally, to Excel or any other format. It does not require any server side programming – the export document is generated on the fly, entirely in JavaScript.
The extension serves as a base for exporting any kind of data, but comes bundled with a .xls export formatter suitable for exporting any Grid straight to Excel. Here’s how to do that:
var grid = new Ext.grid.GridPanel({
store: someStore,
tbar : [
{
xtype: 'exportbutton',
store: someStore
}
],
//your normal grid config goes here
});
Clicking the Download button in the top toolbar iterates over the data in the store and creates an Excel file locally, before Base64 encoding it and redirecting the browser via a data url. If you have Excel or a similar program installed your browser should ask you to save the file or open it with Excel.
I put together a quick example of the plugin in action inside the repository, just clone or download the code and drag the examples/index.html file into your browser to run it.
The Exporter will work with any store or store-based component. It also allows export to any format – for example CSV or PDF. Although the Excel Formatter is probably the most useful, implementing a CSV or other Formatter should be trivial – check out the Excel Formatter example in the ExcelFormatter directory.
Ext.ux.layout.FillContainer
September 28, 2009 by Ed Spencer · 3 Comments
One of the pages on the Ext JS app I’m currently working on has a form with a grid underneath. The page exists as a tab inside an Ext.TabPanel, and uses the border layout, with the form as the ‘north’ component and the grid as ‘center’.
The trouble with this is that the grid shrinks down to an unusable size when the browser window is too small, ending up like this:

We could alternatively use a basic container layout, but this limits us to a fixed height for the grid, meaning we waste space at the bottom:

Enter the imaginatively named FillContainer:
new Ext.Panel({
autoScroll: true,
layout: 'fillcontainer',
items : [
{
html : 'Pretend this is a form',
height: 400
},
{
html : 'And this is the grid',
minHeight : 250,
fillContainer: true
}
]
});
If our containing panel shrinks to less than 650px in height, the grid will be automatically sized to 250px and a vertical scrollbar will appear on the panel, like this:

If the panel’s height increases to, say, 900px, the grid gets resized to 500px high. This way we use the space when it’s available, while maintaining a usable interface when height is limited:

Here’s the code that makes it work:
Ext.ns('Ext.ux.layout');
/**
* @class Ext.ux.layout.FillContainerLayout
* @extends Ext.layout.ContainerLayout
* @author Ed Spencer (http://edspencer.net)
* Extended version of container layout which expands a given child item to the
* full height of the container, honouring the item's minHeight property
*/
Ext.ux.layout.FillContainerLayout = Ext.extend(Ext.layout.ContainerLayout, {
monitorResize: true,
/**
* After rendering each item, resize the one with fillContainer == true
*/
onLayout: function(ct, target) {
Ext.ux.layout.FillContainerLayout.superclass.onLayout.apply(this, arguments);
var ctHeight = ct.getHeight(),
itemsHeight = 0,
expandItem;
ct.items.each(function(item) {
if (item.fillContainer === true) {
expandItem = item;
} else {
itemsHeight += item.getHeight();
}
});
//set the expand item's height to fill the container
if (expandItem != undefined && ctHeight > itemsHeight) {
var newHeight = ctHeight - itemsHeight;
expandItem.setHeight(Math.max(newHeight, expandItem.minHeight));
}
}
});
Ext.Container.LAYOUTS['fillcontainer'] = Ext.ux.layout.FillContainerLayout;
As we’re just extending the default container layout, your items will be rendered in the order you specify them. The expanding item doesn’t have to be the last one – we could equally have set fillContainer and minHeight on the form to expand that instead of the grid.
Using the ExtJS Row Editor
September 16, 2009 by Ed Spencer · 5 Comments
The RowEditor plugin was recently added to the ExtJS examples page. It works a lot like a normal Grid Editor, except you can edit several fields on a given row at once before saving.
This neatly solves the problem of adding a new row to an editor grid, entering data into the first field and finding it save itself straight away, which is rarely desired. In this fashion we can provide full CRUD for simple models in a single page.
Installation
You’ll need to get a copy of the javascript, css and images from the server. This is a bit of a pain. If you still have the ExtJS SDK around you can find these in the examples folder, if not you can get each file as follows:
Grab the plugin JS file below and put it where you usually put your .js files:
http://www.extjs.com/deploy/dev/examples/ux/RowEditor.js
This needs to go with your other stylesheets, usually in a directory called ‘css’:
http://www.extjs.com/deploy/dev/examples/ux/css/RowEditor.css
Download these two images and put them into your existing ‘images’ folder (the same place the other ExtJS images live):
http://www.extjs.com/deploy/dev/examples/ux/images/row-editor-bg.gif
http://www.extjs.com/deploy/dev/examples/ux/images/row-editor-btns.gif
Include the .js and .css files on your page and you should be ready to go.
Usage
RowEditor is a normal grid plugin, so you’ll need to instantiate it and add to your grid’s ‘plugins’ property. You also need to define what type of Editor is available (if any) on each column:
var editor = new Ext.ux.grid.RowEditor();
var grid = new Ext.grid.GridPanel({
plugins: [editor],
columns: [
{
header : 'User Name',
dataIndex: 'name',
editor : new Ext.form.TextField()
},
{
header : 'Email',
dataIndex: 'email',
editor : new Ext.form.TextField()
}
]
... the rest of your grid config here
});
RowEditor defines a few events, the most useful one being ‘afteredit’. Its signature looks like this:
/**
* @event afteredit
* Fired after a row is edited and passes validation. This event is fired
* after the store's update event is fired with this edit.
* @param {Ext.ux.grid.RowEditor} roweditor This object
* @param {Object} changes Object with changes made to the record.
* @param {Ext.data.Record} r The Record that was edited.
* @param {Number} rowIndex The rowIndex of the row just edited
*/
'afteredit'
All you need to do is listen to that event on your RowEditor and save your model object appropriately. First though, we’ll define the Ext.data.Record that we’re using in this grid’s store:
var User = Ext.data.Record.create([
{name: 'user_id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'email', type: 'string'}
]);
And now the afteredit listener itself
editor.on({
scope: this,
afteredit: function(roweditor, changes, record, rowIndex) {
//your save logic here - might look something like this:
Ext.Ajax.request({
url : record.phantom ? '/users' : '/users/' + record.get('user_id'),
method: record.phantom ? 'POST' : 'PUT',
params: changes,
success: function() {
//post-processing here - this might include reloading the grid if there are calculated fields
}
});
}
});
The code above simply takes the changes object (which is just key: value object with all the changed fields) and issues a request to your server backend. ‘record.phantom’ returns true if this record does not yet exist on the server – we use this information above to specify whether we’re POSTing to /users or PUTing to /users/123, in line with normal RESTful practices.
Adding a new record
The example above allows for editing an existing record, but how do we add a new one? Like this:
var grid = new Ext.grid.GridPanel({
//... the same config from above goes here,
tbar: [
{
text : "Add User",
handler: function() {
//make a new empty User and stop any current editing
var newUser = new User({});
rowEditor.stopEditing();
//add our new record as the first row, select it
grid.store.insert(0, newUser);
grid.getView().refresh();
grid.getSelectionModel().selectRow(0);
//start editing our new User
rowEditor.startEditing(0);
}
}
]
});
Pretty simple stuff – we’ve just added a toolbar with a button which, when clicked, creates a new User record, inserts it at the top of the grid and focusses the RowEditor on it.
Configuration Options
Although not documented, the plugin has a few configuration options:
var editor = new Ext.ux.grid.RowEditor({
saveText : "My Save Button Text",
cancelText: "My Cancel Button Text",
clicksToEdit: 1, //this changes from the default double-click activation to single click activation
errorSummary: false //disables display of validation messages if the row is invalid
});
If you want to customise other elements of the RowEditor you probably can, but you’ll need to take a look at the source (it’s not scary).
Final Thought
RowEditor is a really nice component which can provide an intuitive interface and save you writing a lot of CRUD code. It is best employed on grids with only a few columns – for models with lots of data fields you’re better off with a full FormPanel.
I’d be pretty happy to see this included in the default ExtJS distribution, as I find myself returning to it frequently.
Ext.decorate
August 30, 2009 by Ed Spencer · Leave a Comment
Sometimes you want to override one of the methods in ExtJS that return a configuration object – let’s use Ext.direct.RemotingProvider’s getCallData as an example, which looks like this:
getCallData: function(t){
return {
action: t.action,
method: t.method,
data : t.data,
type : 'rpc',
tid : t.tid
};
}
Our aim is to add an ‘authentication_token’ property to the returned object. You could provide the full config object again in an override, but usually you’re overriding to add, remove or change one or two properties and want to leave the rest unmolested. I used to find myself writing a lot of code with this pattern:
//just adds an authentication token to the call data, for context see <a href="http://www.extjs.com/forum/showthread.php?p=378912#post378912">this forum thread</a>
(function() {
var originalGetCallData = Ext.direct.RemotingProvider.prototype.getCallData;
Ext.override(Ext.direct.RemotingProvider, {
getCallData: function(t) {
var defaults = originalGetCallData.apply(this, arguments);
return Ext.apply(defaults, {
authenticity_token: '<%= form_authenticity_token %>'
});
}
})
})();
All we’re really doing here is adding 1 config item – an authenticity_token, but it takes a lot of setup code to make that happen. Check out Ext.decorate:
/**
* @param {Function} klass The constructor function of the class to override (e.g. Ext.direct.RemotingProvider)
* @param {String} property The name of the property the function to override is tied to on the klass' prototype
* @param {Object} config An object that is Ext.apply'd to the usual return value of the function before returning
*/
Ext.decorate = function(klass, property, config) {
var original = klass.prototype[property];
override = {};
override[property] = function() {
var value = original.apply(this, arguments);
return Ext.apply(value, config);
};
Ext.override(klass, override);
}
This lets us write the same override like this:
Ext.decorate(Ext.direct.RemotingProvider, 'getCallData', {
authenticity_token: '<%= form_authenticity_token %>'
});
Much nicer, we just tell it what we want with no need for unwieldy boilerplate code. This method doesn’t actually exist in Ext (though it would be good if something similar did), but you could define it yourself as above to keep such code nice and dry.