X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/2e847cf21b8ab9d15fa167b315ca5b2fa92638fc..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 @@ +
\ No newline at end of file/** + * @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(); + } +}); +