PDA

View Full Version : Custom look for a widget - modifying the template?



vargadanis
14 Nov 2009, 5:11 AM
Hello all,
I've been digging into ExtJS a little and I found a challenge, that I could no solve myself.
I made a little paste that describes my problem:
http://pastebin.com/f2e430e (http://pastebin.com/m7c3049d2)

Basically what I'd like to do is put 1-1 small image before and after the combo box's input and image field.
I am not sure what is a good approach for this. Creating a new widget that extends combobox? Modifying the template for the combobox? What do I need to do to achieve this result?

vargadanis
16 Nov 2009, 1:54 AM
Ok, well I thought I'd give my solution to my own problem. I know this is far from perfect so I need your input on it.

So basically what I did wasn't to modify the existing templates for the widgets but modify them after render.
So say I have an item on formpanel, something like this:


/* ... */
items: [{
xtype: 'combo',
fieldLabel: 'Location',
triggerAction: 'all',
mode: 'local',
name: 'system',
}]
/* ... */Of course I omitted all the config options that are not required to demonstrate my solution.
What I did was writing a function that is called after the combobox was rendered. So I added a listener to the combobox.


/* ... */
items: [{
xtype: 'combo',
fieldLabel: 'Location',
triggerAction: 'all',
mode: 'local',
name: 'system',
listeners: {
afterRender: modifyCombobox
}
}]
/* ... */And the function the modifies the Combobox's layout looks something like:

function modifyTextfield(comp){
var container = comp.container;
var dh = Ext.DomHelper;
var imgLeft = {
tag: 'img',
src: 'images/images/input_left.jpg',
alt: '',
cls: 'float-left'
}
var imgRight = {
tag: 'img',
src: 'images/images/input_right.jpg',
alt: '',
cls: 'float-left'
}
var clrDiv = {
tag: 'div',
clas: 'clear'
}
dh.insertFirst(container, imgLeft);
dh.append(container, imgRight);
dh.append(container, clrDiv);
comp.setWidth(comp.getWidth() - 9 );
}
It uses DomHelper functions to render new tags.
The container var is the div wrapping around the input field and the trigger image (the little arrowed image). So I have to add 2 images before and after those for the rounded edges.

Complication:
The input field and the trigger arrow appear weird in these situations. The container wrapper has a fixed width which you have to manually modify by the sum of the widths of the 2 images that you want to insert. This is what the last line in the function does.

Complication No2:
The styles that are used to display the blue theme in ExtJS make it all appear weird. Some of these were:


The 2nd image that was supposed to be inserted after the trigger arrow get's into new line...
The second image gets in front of the trigger arrow and after the input field of the combo box

Some workarounds: make all these components float left and modify the position of the trigger arrow to relative instead of the default absolute.

Animal
16 Nov 2009, 3:21 AM
OK, you seem to be getting the hang of modifying the DOM structure to suit your needs.

You probably need to implement getTriggerWidth in that ComboBox instance to return the width taken up by all the extra images so that when resizing the widget, the inner <input> can be sized that bit smaller.

The main problem you might have is re-usability if just using listeners to insert ad-hoc code.

A plugin might be your best approach: http://www.extjs.com/blog/2009/11/11/advanced-plugin-development-with-ext-js/

vargadanis
17 Nov 2009, 2:13 AM
Hmm, awesome, thank you for your tips, I am certainly going to look into plugins and will use that getTriggerWidth method. Looks like something I could use :)