3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * FieldContainer is a derivation of {@link Ext.container.Container Container} that implements the
17 * {@link Ext.form.Labelable Labelable} mixin. This allows it to be configured so that it is rendered with
18 * a {@link #fieldLabel field label} and optional {@link #msgTarget error message} around its sub-items.
19 * This is useful for arranging a group of fields or other components within a single item in a form, so
20 * that it lines up nicely with other fields. A common use is for grouping a set of related fields under
21 * a single label in a form.
23 * The container's configured {@link #items} will be layed out within the field body area according to the
24 * configured {@link #layout} type. The default layout is `'autocontainer'`.
26 * Like regular fields, FieldContainer can inherit its decoration configuration from the
27 * {@link Ext.form.Panel#fieldDefaults fieldDefaults} of an enclosing FormPanel. In addition,
28 * FieldContainer itself can pass {@link #fieldDefaults} to any {@link Ext.form.Labelable fields}
29 * it may itself contain.
31 * If you are grouping a set of {@link Ext.form.field.Checkbox Checkbox} or {@link Ext.form.field.Radio Radio}
32 * fields in a single labeled container, consider using a {@link Ext.form.CheckboxGroup}
33 * or {@link Ext.form.RadioGroup} instead as they are specialized for handling those types.
38 * Ext.create('Ext.form.Panel', {
39 * title: 'FieldContainer Example',
44 * xtype: 'fieldcontainer',
45 * fieldLabel: 'Last Three Jobs',
48 * // The body area will contain three text fields, arranged
49 * // horizontally, separated by draggable splitters.
66 * renderTo: Ext.getBody()
69 * # Usage of fieldDefaults
72 * Ext.create('Ext.form.Panel', {
73 * title: 'FieldContainer Example',
78 * xtype: 'fieldcontainer',
79 * fieldLabel: 'Your Name',
81 * defaultType: 'textfield',
83 * // Arrange fields vertically, stretched to full width
89 * // These config values will be applied to both sub-fields, except
90 * // for Last Name which will use its own msgTarget.
97 * fieldLabel: 'First Name',
100 * fieldLabel: 'Last Name',
105 * renderTo: Ext.getBody()
108 * @docauthor Jason Johnston <jason@sencha.com>
110 Ext.define('Ext.form.FieldContainer', {
111 extend: 'Ext.container.Container',
113 labelable: 'Ext.form.Labelable',
114 fieldAncestor: 'Ext.form.FieldAncestor'
116 alias: 'widget.fieldcontainer',
118 componentLayout: 'field',
121 * @cfg {Boolean} combineLabels
122 * If set to true, and there is no defined {@link #fieldLabel}, the field container will automatically
123 * generate its label by combining the labels of all the fields it contains. Defaults to false.
125 combineLabels: false,
128 * @cfg {String} labelConnector
129 * The string to use when joining the labels of individual sub-fields, when {@link #combineLabels} is
130 * set to true. Defaults to ', '.
132 labelConnector: ', ',
135 * @cfg {Boolean} combineErrors
136 * If set to true, the field container will automatically combine and display the validation errors from
137 * all the fields it contains as a single error on the container, according to the configured
138 * {@link #msgTarget}. Defaults to false.
140 combineErrors: false,
142 maskOnDisable: false,
144 initComponent: function() {
146 onSubCmpAddOrRemove = me.onSubCmpAddOrRemove;
150 me.initFieldAncestor();
156 * @protected Called when a {@link Ext.form.Labelable} instance is added to the container's subtree.
157 * @param {Ext.form.Labelable} labelable The instance that was added
159 onLabelableAdded: function(labelable) {
161 me.mixins.fieldAncestor.onLabelableAdded.call(this, labelable);
166 * @protected Called when a {@link Ext.form.Labelable} instance is removed from the container's subtree.
167 * @param {Ext.form.Labelable} labelable The instance that was removed
169 onLabelableRemoved: function(labelable) {
171 me.mixins.fieldAncestor.onLabelableRemoved.call(this, labelable);
175 onRender: function() {
178 me.onLabelableRender();
180 me.callParent(arguments);
183 initRenderTpl: function() {
185 if (!me.hasOwnProperty('renderTpl')) {
186 me.renderTpl = me.getTpl('labelableRenderTpl');
188 return me.callParent();
191 initRenderData: function() {
192 return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
196 * Returns the combined field label if {@link #combineLabels} is set to true and if there is no
197 * set {@link #fieldLabel}. Otherwise returns the fieldLabel like normal. You can also override
198 * this method to provide a custom generated label.
200 getFieldLabel: function() {
201 var label = this.fieldLabel || '';
202 if (!label && this.combineLabels) {
203 label = Ext.Array.map(this.query('[isFieldLabelable]'), function(field) {
204 return field.getFieldLabel();
205 }).join(this.labelConnector);
211 * @private Updates the content of the labelEl if it is rendered
213 updateLabel: function() {
217 label.update(me.getFieldLabel());
223 * @private Fired when the error message of any field within the container changes, and updates the
224 * combined error message to match.
226 onFieldErrorChange: function(field, activeError) {
227 if (this.combineErrors) {
229 oldError = me.getActiveError(),
230 invalidFields = Ext.Array.filter(me.query('[isFormField]'), function(field) {
231 return field.hasActiveError();
233 newErrors = me.getCombinedErrors(invalidFields);
236 me.setActiveErrors(newErrors);
238 me.unsetActiveError();
241 if (oldError !== me.getActiveError()) {
242 me.doComponentLayout();
248 * Takes an Array of invalid {@link Ext.form.field.Field} objects and builds a combined list of error
249 * messages from them. Defaults to prepending each message by the field name and a colon. This
250 * can be overridden to provide custom combined error message handling, for instance changing
251 * the format of each message or sorting the array (it is sorted in order of appearance by default).
252 * @param {Ext.form.field.Field[]} invalidFields An Array of the sub-fields which are currently invalid.
253 * @return {String[]} The combined list of error messages
255 getCombinedErrors: function(invalidFields) {
256 var forEach = Ext.Array.forEach,
258 forEach(invalidFields, function(field) {
259 forEach(field.getActiveErrors(), function(error) {
260 var label = field.getFieldLabel();
261 errors.push((label ? label + ': ' : '') + error);
267 getTargetEl: function() {
268 return this.bodyEl || this.callParent();