/** * @class Ext.form.FieldContainer * @extends Ext.container.Container *

A container which participates in {@link Ext.layout.component.form.Field field layout}. * This allows grouping of several components with a {@link #fieldLabel field label} and optional * {@link #msgTarget error message}, so that it lines up nicely with other fields in a form. The * {@link #items} of the container will be layed out within the field body area according to the * configured {@link #layout}.

*

Like regular fields, FieldContainer can inherit its decoration configuration from the * {@link Ext.form.FormPanel#fieldDefaults fieldDefaults} of an enclosing FormPanel. In addition, * FieldContainer itself can pass {@link #fieldDefaults} to any {@link Ext.form.Labelable fields} * it may itself contain.

*

Example usage:

*
Ext.create('Ext.form.FormPanel', {
    renderTo: Ext.getBody(),
    title: 'FieldContainer Examples',
    width: 600,
    bodyPadding: 10,

    items: [{
        fieldLabel: 'Panels',
        xtype: 'fieldcontainer',
        layout: 'hbox',
        defaults: {
            height: 50,
            flex: 1
        },
        items: [{
            xtype: 'panel',
            title: 'Panel 1'
        }, {
            xtype: 'splitter'
        }, {
            xtype: 'panel',
            title: 'Panel 2'
        }, {
            xtype: 'splitter'
        }, {
            xtype: 'panel',
            title: 'Panel 3'
        }]
    }]
});
* @constructor * Creates a new Ext.form.FieldContainer instance. * @param {Object} config The component configuration. * * @xtype fieldcontainer */ Ext.define('Ext.form.FieldContainer', { extend: 'Ext.container.Container', mixins: { decoratable: 'Ext.form.Labelable' }, alias: 'widget.fieldcontainer', componentLayout: 'field',
/** * @cfg {Object} fieldDefaults *

If specified, the properties in this object are used as default config values for each * {@link Ext.form.Labelable} instance (e.g. {@link Ext.form.BaseField} or {@link Ext.form.FieldContainer}) * that is added as a descendant of this FieldContainer. Corresponding values specified in an individual field's * own configuration, or from the {@link Ext.lib.Container#defaults defaults config} of its parent container, * will take precedence. See the documentation for {@link Ext.form.Labelable} to see what config * options may be specified in the fieldDefaults.

*

Example:

*
new Ext.form.FieldContainer({
    fieldDefaults: {
        labelAlign: 'left',
        labelWidth: 100
    },
    items: [{
        xtype: 'fieldset',
        defaults: {
            labelAlign: 'top'
        },
        items: [{
            name: 'field1'
        }, {
            name: 'field2'
        }]
    }, {
        xtype: 'fieldset',
        items: [{
            name: 'field3',
            labelWidth: 150
        }, {
            name: 'field4'
        }]
    }]
});
*

In this example, field1 and field2 will get labelAlign:'top' (from the fieldset's defaults) * and labelWidth:100 (from fieldDefaults), field3 and field4 will both get labelAlign:'left' (from * fieldDefaults and field3 will use the labelWidth:150 from its own config.

*/ initComponent: function() { var me = this; // Init mixin me.initLabelable(); // Catch addition of descendant fields me.on('add', me.onSubCmpAdded, me); me.callParent(); }, /** * @private * Handle the addition of components to the FieldContainer's child tree, copying the * fieldDefaults to individual fields as necessary. */ onSubCmpAdded: function(parent, child) { var me = this, fieldDefaults = me.fieldDefaults; function handleCmp(cmp) { if (cmp.isFieldLabelable) { cmp.applyFieldDefaults(fieldDefaults); } else if (cmp.isContainer) { cmp.items.each(handleCmp); } } if (fieldDefaults) { handleCmp(child); } }, onRender: function() { var me = this, renderSelectors = me.renderSelectors, applyIf = Ext.applyIf; applyIf(renderSelectors, me.getLabelableSelectors()); me.callParent(arguments); }, initRenderTpl: function() { var me = this; if (!me.hasOwnProperty('renderTpl')) { me.renderTpl = me.labelableRenderTpl; } return me.callParent(); }, initRenderData: function() { return Ext.applyIf(this.callParent(), this.getLabelableRenderData()); }, getTargetEl: function() { return this.bodyEl || this.callParent(); } /* TODO merging fieldDefaults objects down doesn't work due to the order of component addition applyFieldDefaults: function(defaults) { this.getMixin('decoratable').applyFieldDefaults.call(this, defaults); // merge defaults with our own this.fieldDefaults = Ext.apply({}, this.fieldDefaults, defaults); }*/ });