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 * @class Ext.form.FieldAncestor
18 A mixin for {@link Ext.container.Container} components that are likely to have form fields in their
19 items subtree. Adds the following capabilities:
21 - Methods for handling the addition and removal of {@link Ext.form.Labelable} and {@link Ext.form.field.Field}
22 instances at any depth within the container.
23 - Events ({@link #fieldvaliditychange} and {@link #fielderrorchange}) for handling changes to the state
24 of individual fields at the container level.
25 - Automatic application of {@link #fieldDefaults} config properties to each field added within the
26 container, to facilitate uniform configuration of all fields.
28 This mixin is primarily for internal use by {@link Ext.form.Panel} and {@link Ext.form.FieldContainer},
29 and should not normally need to be used directly.
32 * @docauthor Jason Johnston <jason@sencha.com>
34 Ext.define('Ext.form.FieldAncestor', {
37 * @cfg {Object} fieldDefaults
38 * <p>If specified, the properties in this object are used as default config values for each
39 * {@link Ext.form.Labelable} instance (e.g. {@link Ext.form.field.Base} or {@link Ext.form.FieldContainer})
40 * that is added as a descendant of this container. Corresponding values specified in an individual field's
41 * own configuration, or from the {@link Ext.container.Container#defaults defaults config} of its parent container,
42 * will take precedence. See the documentation for {@link Ext.form.Labelable} to see what config
43 * options may be specified in the <tt>fieldDefaults</tt>.</p>
45 * <pre><code>new Ext.form.Panel({
70 * <p>In this example, field1 and field2 will get labelAlign:'top' (from the fieldset's <tt>defaults</tt>)
71 * and labelWidth:100 (from <tt>fieldDefaults</tt>), field3 and field4 will both get labelAlign:'left' (from
72 * <tt>fieldDefaults</tt> and field3 will use the labelWidth:150 from its own config.</p>
77 * @protected Initializes the FieldAncestor's state; this must be called from the initComponent method
78 * of any components importing this mixin.
80 initFieldAncestor: function() {
82 onSubtreeChange = me.onFieldAncestorSubtreeChange;
86 * @event fieldvaliditychange
87 * Fires when the validity state of any one of the {@link Ext.form.field.Field} instances within this
89 * @param {Ext.form.FieldAncestor} this
90 * @param {Ext.form.Labelable} The Field instance whose validity changed
91 * @param {String} isValid The field's new validity state
93 'fieldvaliditychange',
96 * @event fielderrorchange
97 * Fires when the active error message is changed for any one of the {@link Ext.form.Labelable}
98 * instances within this container.
99 * @param {Ext.form.FieldAncestor} this
100 * @param {Ext.form.Labelable} The Labelable instance whose active error was changed
101 * @param {String} error The active error message
106 // Catch addition and removal of descendant fields
107 me.on('add', onSubtreeChange, me);
108 me.on('remove', onSubtreeChange, me);
110 me.initFieldDefaults();
114 * @private Initialize the {@link #fieldDefaults} object
116 initFieldDefaults: function() {
117 if (!this.fieldDefaults) {
118 this.fieldDefaults = {};
124 * Handle the addition and removal of components in the FieldAncestor component's child tree.
126 onFieldAncestorSubtreeChange: function(parent, child) {
128 isAdding = !!child.ownerCt;
130 function handleCmp(cmp) {
131 var isLabelable = cmp.isFieldLabelable,
132 isField = cmp.isFormField;
133 if (isLabelable || isField) {
135 me['onLabelable' + (isAdding ? 'Added' : 'Removed')](cmp);
138 me['onField' + (isAdding ? 'Added' : 'Removed')](cmp);
141 else if (cmp.isContainer) {
142 Ext.Array.forEach(cmp.getRefItems(), handleCmp);
149 * @protected Called when a {@link Ext.form.Labelable} instance is added to the container's subtree.
150 * @param {Ext.form.Labelable} labelable The instance that was added
152 onLabelableAdded: function(labelable) {
155 // buffer slightly to avoid excessive firing while sub-fields are changing en masse
156 me.mon(labelable, 'errorchange', me.handleFieldErrorChange, me, {buffer: 10});
158 labelable.setFieldDefaults(me.fieldDefaults);
162 * @protected Called when a {@link Ext.form.field.Field} instance is added to the container's subtree.
163 * @param {Ext.form.field.Field} field The field which was added
165 onFieldAdded: function(field) {
167 me.mon(field, 'validitychange', me.handleFieldValidityChange, me);
171 * @protected Called when a {@link Ext.form.Labelable} instance is removed from the container's subtree.
172 * @param {Ext.form.Labelable} labelable The instance that was removed
174 onLabelableRemoved: function(labelable) {
176 me.mun(labelable, 'errorchange', me.handleFieldErrorChange, me);
180 * @protected Called when a {@link Ext.form.field.Field} instance is removed from the container's subtree.
181 * @param {Ext.form.field.Field} field The field which was removed
183 onFieldRemoved: function(field) {
185 me.mun(field, 'validitychange', me.handleFieldValidityChange, me);
189 * @private Handle validitychange events on sub-fields; invoke the aggregated event and method
191 handleFieldValidityChange: function(field, isValid) {
193 me.fireEvent('fieldvaliditychange', me, field, isValid);
194 me.onFieldValidityChange();
198 * @private Handle errorchange events on sub-fields; invoke the aggregated event and method
200 handleFieldErrorChange: function(labelable, activeError) {
202 me.fireEvent('fielderrorchange', me, labelable, activeError);
203 me.onFieldErrorChange();
207 * @protected Fired when the validity of any field within the container changes.
208 * @param {Ext.form.field.Field} The sub-field whose validity changed
209 * @param {String} The new validity state
211 onFieldValidityChange: Ext.emptyFn,
214 * @protected Fired when the error message of any field within the container changes.
215 * @param {Ext.form.Labelable} The sub-field whose active error changed
216 * @param {String} The new active error message
218 onFieldErrorChange: Ext.emptyFn