X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/530ef4b6c5b943cfa68b779d11cf7de29aa878bf..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/docs/source/FieldContainer.html diff --git a/docs/source/FieldContainer.html b/docs/source/FieldContainer.html new file mode 100644 index 00000000..1853edec --- /dev/null +++ b/docs/source/FieldContainer.html @@ -0,0 +1,268 @@ +Sencha Documentation Project
/**
+ * @class Ext.form.FieldContainer
+ * @extends Ext.container.Container
+
+FieldContainer is a derivation of {@link Ext.container.Container Container} that implements the
+{@link Ext.form.Labelable Labelable} mixin. This allows it to be configured so that it is rendered with
+a {@link #fieldLabel field label} and optional {@link #msgTarget error message} around its sub-items.
+This is useful for arranging a group of fields or other components within a single item in a form, so
+that it lines up nicely with other fields. A common use is for grouping a set of related fields under
+a single label in a form.
+
+The container's configured {@link #items} will be layed out within the field body area according to the
+configured {@link #layout} type. The default layout is `'autocontainer'`.
+
+Like regular fields, FieldContainer can inherit its decoration configuration from the
+{@link Ext.form.Panel#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.
+
+If you are grouping a set of {@link Ext.form.field.Checkbox Checkbox} or {@link Ext.form.field.Radio Radio}
+fields in a single labeled container, consider using a {@link Ext.form.CheckboxGroup}
+or {@link Ext.form.RadioGroup} instead as they are specialized for handling those types.
+{@img Ext.form.FieldContainer/Ext.form.FieldContainer1.png Ext.form.FieldContainer component}
+__Example usage:__
+
+    Ext.create('Ext.form.Panel', {
+        title: 'FieldContainer Example',
+        width: 550,
+        bodyPadding: 10,
+    
+        items: [{
+            xtype: 'fieldcontainer',
+            fieldLabel: 'Last Three Jobs',
+            labelWidth: 100,
+    
+            // The body area will contain three text fields, arranged
+            // horizontally, separated by draggable splitters.
+            layout: 'hbox',
+            items: [{
+                xtype: 'textfield',
+                flex: 1
+            }, {
+                xtype: 'splitter'
+            }, {
+                xtype: 'textfield',
+                flex: 1
+            }, {
+                xtype: 'splitter'
+            }, {
+                xtype: 'textfield',
+                flex: 1
+            }]
+        }],
+        renderTo: Ext.getBody()
+    });
+
+__Usage of {@link #fieldDefaults}:__
+{@img Ext.form.FieldContainer/Ext.form.FieldContainer2.png Ext.form.FieldContainer component}
+
+    Ext.create('Ext.form.Panel', {
+        title: 'FieldContainer Example',
+        width: 350,
+        bodyPadding: 10,
+    
+        items: [{
+            xtype: 'fieldcontainer',
+            fieldLabel: 'Your Name',
+            labelWidth: 75,
+            defaultType: 'textfield',
+    
+            // Arrange fields vertically, stretched to full width
+            layout: 'anchor',
+            defaults: {
+                layout: '100%'
+            },
+    
+            // These config values will be applied to both sub-fields, except
+            // for Last Name which will use its own msgTarget.
+            fieldDefaults: {
+                msgTarget: 'under',
+                labelAlign: 'top'
+            },
+    
+            items: [{
+                fieldLabel: 'First Name',
+                name: 'firstName'
+            }, {
+                fieldLabel: 'Last Name',
+                name: 'lastName',
+                msgTarget: 'under'
+            }]
+        }],
+        renderTo: Ext.getBody()
+    });
+
+
+ * @constructor
+ * Creates a new Ext.form.FieldContainer instance.
+ * @param {Object} config The component configuration.
+ *
+ * @xtype fieldcontainer
+ * @markdown
+ * @docauthor Jason Johnston <jason@sencha.com>
+ */
+Ext.define('Ext.form.FieldContainer', {
+    extend: 'Ext.container.Container',
+    mixins: {
+        labelable: 'Ext.form.Labelable',
+        fieldAncestor: 'Ext.form.FieldAncestor'
+    },
+    alias: 'widget.fieldcontainer',
+
+    componentLayout: 'field',
+
+    /**
+     * @cfg {Boolean} combineLabels
+     * If set to true, and there is no defined {@link #fieldLabel}, the field container will automatically
+     * generate its label by combining the labels of all the fields it contains. Defaults to false.
+     */
+    combineLabels: false,
+
+    /**
+     * @cfg {String} labelConnector
+     * The string to use when joining the labels of individual sub-fields, when {@link #combineLabels} is
+     * set to true. Defaults to ', '.
+     */
+    labelConnector: ', ',
+
+    /**
+     * @cfg {Boolean} combineErrors
+     * If set to true, the field container will automatically combine and display the validation errors from
+     * all the fields it contains as a single error on the container, according to the configured
+     * {@link #msgTarget}. Defaults to false.
+     */
+    combineErrors: false,
+    
+    maskOnDisable: false,
+
+    initComponent: function() {
+        var me = this,
+            onSubCmpAddOrRemove = me.onSubCmpAddOrRemove;
+
+        // Init mixins
+        me.initLabelable();
+        me.initFieldAncestor();
+
+        me.callParent();
+    },
+
+    /**
+     * @protected Called when a {@link Ext.form.Labelable} instance is added to the container's subtree.
+     * @param {Ext.form.Labelable} labelable The instance that was added
+     */
+    onLabelableAdded: function(labelable) {
+        var me = this;
+        me.mixins.fieldAncestor.onLabelableAdded.call(this, labelable);
+        me.updateLabel();
+    },
+
+    /**
+     * @protected Called when a {@link Ext.form.Labelable} instance is removed from the container's subtree.
+     * @param {Ext.form.Labelable} labelable The instance that was removed
+     */
+    onLabelableRemoved: function(labelable) {
+        var me = this;
+        me.mixins.fieldAncestor.onLabelableRemoved.call(this, labelable);
+        me.updateLabel();
+    },
+
+    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.getTpl('labelableRenderTpl');
+        }
+        return me.callParent();
+    },
+
+    initRenderData: function() {
+        return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
+    },
+
+    /**
+     * Returns the combined field label if {@link #combineLabels} is set to true and if there is no
+     * set {@link #fieldLabel}. Otherwise returns the fieldLabel like normal. You can also override
+     * this method to provide a custom generated label.
+     */
+    getFieldLabel: function() {
+        var label = this.fieldLabel || '';
+        if (!label && this.combineLabels) {
+            label = Ext.Array.map(this.query('[isFieldLabelable]'), function(field) {
+                return field.getFieldLabel();
+            }).join(this.labelConnector);
+        }
+        return label;
+    },
+
+    /**
+     * @private Updates the content of the labelEl if it is rendered
+     */
+    updateLabel: function() {
+        var me = this,
+            label = me.labelEl;
+        if (label) {
+            label.update(me.getFieldLabel());
+        }
+    },
+
+
+    /**
+     * @private Fired when the error message of any field within the container changes, and updates the
+     * combined error message to match.
+     */
+    onFieldErrorChange: function(field, activeError) {
+        if (this.combineErrors) {
+            var me = this,
+                oldError = me.getActiveError(),
+                invalidFields = Ext.Array.filter(me.query('[isFormField]'), function(field) {
+                    return field.hasActiveError();
+                }),
+                newErrors = me.getCombinedErrors(invalidFields);
+
+            if (newErrors) {
+                me.setActiveErrors(newErrors);
+            } else {
+                me.unsetActiveError();
+            }
+
+            if (oldError !== me.getActiveError()) {
+                me.doComponentLayout();
+            }
+        }
+    },
+
+    /**
+     * Takes an Array of invalid {@link Ext.form.field.Field} objects and builds a combined list of error
+     * messages from them. Defaults to prepending each message by the field name and a colon. This
+     * can be overridden to provide custom combined error message handling, for instance changing
+     * the format of each message or sorting the array (it is sorted in order of appearance by default).
+     * @param {Array} invalidFields An Array of the sub-fields which are currently invalid.
+     * @return {Array} The combined list of error messages
+     */
+    getCombinedErrors: function(invalidFields) {
+        var forEach = Ext.Array.forEach,
+            errors = [];
+        forEach(invalidFields, function(field) {
+            forEach(field.getActiveErrors(), function(error) {
+                var label = field.getFieldLabel();
+                errors.push((label ? label + ': ' : '') + error);
+            });
+        });
+        return errors;
+    },
+
+    getTargetEl: function() {
+        return this.bodyEl || this.callParent();
+    }
+});
+
\ No newline at end of file