Introduction
ExtJS is a really cool JavaScript library that contains great form building components. But, like all things, you start using it in anger, and it isn't long before you find something it can't do out-of-the-box and you want to extend it.
I had a form made up of standard Ext.form components, but then I wanted to output a couple of DIV
s amongst the other form elements so that I could render some special content to them. Specifically, I had a report that is broken into sections and each can have files attached to it. I wanted to display a button to bring up a file upload dialog and a list of uploaded files. For interest, the file upload dialog I used can be found here - it is seriously good!
So, it was that I needed to develop an extension to the Ext.component
class that could render out my div
s. This is quite simple, but it took a fair bit of investigation and hunting through the source to find out what was required, so I thought I should create a little demo component and put an article here to save others some time.
If you are looking to specialise an existing component, there is a great example here.
Using the code
Basically, you need three things to make it work (you may even need less, but I implemented these three and then I was happy): initComponent
, onRender
, and afterRender
. Basically, I started from the Ext.Button
class and figured out how it worked, and then applied the chainsaw.
Note the first line that registers a namespace and the last line that registers the control with a unique xtype
that can be used to identify it with ExtJS.
All the good stuff happens in onRender()
. I create a template that is used to render HTML containing the configuration strings text1
and text2
. Then, render this content using the insertBefore()
or append()
function (depending on whether a position for the element has been supplied). These functions perform the replacements in the template string from the argument targs
.
Ext.namespace('Ext.ensigma');
Ext.ensigma.DemoComponent = Ext.extend(Ext.Component, {
initComponent : function(){
Ext.ensigma.DemoComponent.superclass.initComponent.call(this);
},
onRender : function(ct, position){
if(!this.template){
if(!Ext.ensigma.DemoComponent.filesetTemplate){
Ext.ensigma.DemoComponent.filesetTemplate = new Ext.Template(
'<div><div>{0}</div><div>{1}</div></div>'
);
}
this.template = Ext.ensigma.DemoComponent.filesetTemplate;
}
var fs, targs = [this.text1 || ' ', this.text2 || ' '];
if(position){
fs = this.template.insertBefore(position, targs, true);
}else{
fs = this.template.append(ct, targs, true);
}
this.el = fs;
}
afterRender : function(){
Ext.ensigma.DemoComponent.superclass.afterRender.call(this);
}
});
Ext.reg('fileset', Ext.ensigma.DemoComponent);
Here is the example code that uses the component:
Ext.onReady(function(){
Ext.QuickTips.init();
var simple = new Ext.FormPanel({
labelWidth: 75,
frame:true,
title: 'Fileset Form',
bodyStyle:'padding:5px 5px 0',
width: 350,
defaults: {width: 230},
defaultType: 'textfield',
items: [new Ext.form.TextField ({
fieldLabel: 'First Name',
name: 'first',
allowBlank:false
}), new Ext.ensigma.DemoComponent ({
text1: 'hello world',
text2: 'goodbye cruel world',
autoWidth: true
})
]
});
simple.render(document.body);
});
Tips
Care should be taken never to have trailing commas at the end of lists; for example, [1,2,3] should never be coded like [1,2,3,]. In Firefox (as in C), the [1,2,3,] is a three item list; in IE, it is a four item list where the final item is undefined. The extra list item results in errors in IE, and sometimes even shows a blank document with no error message. Depending on where you have the trailing comma, any of the following messages may be displayed:
- Error: 'events' is null or not an object
- Error: Expected identifier string or number
- Error: 'undefined' is null or not an object
History
- 12-May-2008
- Added the
this.el = fs
line to onRender(...)
. This is required in some instances to keep IE happy and/or when the component is included in a container. - Added note on trailing commas and resulting error messages.