View Full Version : Component layouts - how to write a form element component layout?

5 Sep 2011, 6:46 AM
I'm currently trying to build a custom Ext JS 4 form element which inherits from the combo box form element and should be auto-growing (something like the well-known SuperBoxSelect). To implement element sizing it thought it might be best to use a custom component layout (inheriting from Ext.layout.component.field.Field).

This is the current code

Ext.define('TQ.layout.component.field.MultiSelect', {
alias: ['layout.tq-multiSelect'],
extend: 'Ext.layout.component.field.Field',

type: 'tq-multiSelect',

setTargetSize : function(width, height) {
this.callParent([width, Math.max(this.owner.listEl.getHeight() + this.owner.wrapEl.getFrameWidth('tb'), height)]);

sizeBody: function(info) {
info.height = Math.max(this.owner.listEl.getHeight() + this.owner.wrapEl.getFrameWidth('tb'), info.height);

sizeBodyContents: function(width, height) {
var me = this,
owner = me.owner,
listEl = owner.listEl,
wrapEl = owner.wrapEl,
triggerWrap = owner.triggerWrap,
triggerWidth = owner.getTriggerWidth();
// If we or our ancestor is hidden, we can get a triggerWidth calculation
// of 0. We don't want to resize in this case.
if (owner.hideTrigger || owner.readOnly || triggerWidth > 0) {
// Decrease the field's width by the width of the triggers. Both the field and the triggerWrap
// are floated left in CSS so they'll stack up side by side.
me.setElementSize(listEl, Ext.isNumber(width) ? width - triggerWidth - wrapEl.getFrameWidth('lr') : width);

// Explicitly set the triggerWrap's width, to prevent wrapping
me.setElementSize(wrapEl, null, height);

which works - at least as long as I do not change the contents of the owning container element after the layout has been applied. The problem seems to be the setTargetSize override in which I mess with the owning element size to reserve enough space for the auto-growing form element. After removing the form element from its container, the container size is not being reset because the target sizing has been written to the DOM element.

Perhaps this approach is completely stupid - but how would I implement an auto-growing form field component layout then? Is there any in-depth information available on this component layout stuff?

I hope the problem is somewhat clear... If not - please ask and I'll try to add more code or a better explanation.

Best regards


5 Sep 2011, 11:50 PM
I don't really understand what you mean by auto-growing but if you want an Ext 4 version of SuperBoxSelect try:


If not then you'll have to explain what you mean by auto-growing... I can think of half a dozen things that might mean. It may also help to include a full test case so that we can see your custom component in action and what goes wrong.

6 Sep 2011, 1:23 AM
Thanks for the link to the Ext 4 version of SuperBoxSelect. That's more or less the form element we're trying to build - but actually we're facing the same problem when using this element.
Let's try to explain the problem a little bit beter - unfortunately building a running example is not that easy because the form element is integrated in a search panel which uses a rather complicated layout.

The panel consists of

main panel ("anchor" layout)

multiple row panels (anchor "100%", "hbox" layout)

a dropdown form element (width 90px)
a criteria panel (flex 1, "hbox" layout)

(in the current case) a multi-select form element (flex 1)

some controls (width 12px)

The problem now is that multi-select element grows in height when you add elements to it (see the examples (http://kveeiv.github.com/extjs-boxselect/examples/boxselect.html)). But in our case the parent elements are not notified about the height change, so both the criteria panel and the row panel keep their height and the multi-select element is cut off.

Is there any chance that I can trigger a recalculation of the component heights?

If I find some time, I can try to put together a rather standard example of what we try to achieve.

Best regards


7 Sep 2011, 10:49 PM
This all sounds very complicated. It's fighting the usual direction of the layout hierarchy.

Take a look at bindToOwnerCtContainer. For nested layouts this provides a way to inform the parent layout that the child layout has been redone. If you were to set bindToOwnerCtContainer: true on the relevant container layouts and then implemented equivalent functionality in your layout then it might just work.

That said, I'd do some experimental hacking to confirm before I started doing anything this complicated. Hack in something to force a re-layout on the outermost container when the combo resizes, see if it actually works. You could just do it manually from Firebug. There's not much point adding in complex code to propagate up the layout calls if it won't work anyway.

13 Sep 2011, 7:08 AM
Actually it was the clearInnerCtOnLayout (http://docs.sencha.com/ext-js/4-0/#!/api/Ext.layout.container.Box-cfg-clearInnerCtOnLayout) property on the box layouts which caused the containers to be resized correctly.
Thanks for your help and your efforts.

Best regards