Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / guides / forms / README.md
1 # Forms
2 ______________________________________________
3
4 A {@link Ext.form.Panel Form Panel} is nothing more than a basic {@link Ext.panel.Panel Panel} with form handling abilities added.
5 Form Panels can be used throughout an Ext application wherever there is a need to collect data from the user.
6 In addition, Form Panels can use any {@link Ext.layout.container.Container Container Layout}, providing a convenient and flexible way to handle the positioning of their fields.
7 Form Panels can also be bound to a {@link Ext.data.Model Model}, making it easy to load data from and submit data back to the server.
8 Under the hood a Form Panel wraps a {@link Ext.form.Basic Basic Form} which handles all of its input field management, validation, submission, and form loading services.
9 This means that any of the config options of a Basic Form can be used directly on a Form Panel.
10
11 ## Basic Form Panel
12
13 To start off, here's how to create a simple form that collects user data:
14
15     @example
16     Ext.create('Ext.form.Panel', {
17         renderTo: Ext.getBody(),
18         title: 'User Form',
19         height: 130,
20         width: 280,
21         bodyPadding: 10,
22         defaultType: 'textfield',
23         items: [
24             {
25                 fieldLabel: 'First Name',
26                 name: 'firstName'
27             },
28             {
29                 fieldLabel: 'Last Name',
30                 name: 'lastName'
31             },
32             {
33                 xtype: 'datefield',
34                 fieldLabel: 'Date of Birth',
35                 name: 'birthDate'
36             }
37         ]
38     });
39
40 This form renders itself to the document body and has three {@link Ext.form.field.Field Field}s - "First Name", "Last Name", and "Date of Birth". Fields are added to the Form Panel using the {@link Ext.form.Panel#cfg-items items} configuration.
41 The {@link Ext.form.Labelable#fieldLabel fieldLabel} configuration defines what text will appear in the label next to the field, and the {@link Ext.form.field.Base#name name} configuration becomes the `name` attribute of the underlying html field.
42 Notice how this Form Panel has a {@link Ext.form.Panel#defaultType defaultType} of 'textfield'.  This means that any of its items that do not have an {@link Ext.Component xtype} specified (the "First Name" and "Last Name" fields in this example), are {@link Ext.form.field.Text Text Field}s.
43 The "Date of Birth" field on the other hand has its `xtype` explicitly defined as 'datefield' which makes it a {@link Ext.form.field.Date Date Field}. Date Fields expect to only contain valid date data, and come with a {@link Ext.menu.DatePicker DatePicker} for selecting a date.
44
45 See the [Simple Form](guides/forms/examples/simple_form/index.html) example for a live demo.
46
47 ## Fields
48
49 ### Field Types
50
51 Ext JS provides a set of standard Field types out of the box. Any of the Fields in the `Ext.form.field` namespace can be used in a Form Panel. For more information see the API documentaion for each Field type:
52
53 * {@link Ext.form.field.Checkbox}
54 * {@link Ext.form.field.ComboBox}
55 * {@link Ext.form.field.Date}
56 * {@link Ext.form.field.Display}
57 * {@link Ext.form.field.File}
58 * {@link Ext.form.field.Hidden}
59 * {@link Ext.form.field.HtmlEditor}
60 * {@link Ext.form.field.Number}
61 * {@link Ext.form.field.Radio}
62 * {@link Ext.form.field.Text}
63 * {@link Ext.form.field.TextArea}
64 * {@link Ext.form.field.Time}
65
66 ### Validation
67
68 #### 1. Built-in Validations
69
70 Ext JS has built in support for validation on any type of Field, and some Fields have built in validation rules.
71 For example if a value is entered into a {@link Ext.form.field.Date Date Field} and that value cannot be converted into a `Date`, the Field will have the `x-form-invalid-field` CSS class added to its HTML element.
72 If necessary, this CSS class can be changed using the {@link Ext.form.field.Base#invalidCls invalidCls} configuration. In the default [theme](#/guide/theming), adding the `invalidCls` adds a red "invalid underline":
73
74 {@img invalid_field.png Invalid Field}
75
76 A Field containing invalid data will also display an error message. By default this message displays as a tool tip:
77
78 {@img invalid_field_hover.png Invalid Field Hover}
79
80 It's easy to change the location of a Field's error message using the {@link Ext.form.Labelable#msgTarget msgTarget} configuration, and the {@link Ext.form.field.Base#invalidText invalidText} configuration changes the error message.
81 Each Field provides its own implementation of `invalidText`, and many support token replacement in the error message.
82 For example, in a Date Field's `invalidText`, any occurrences of "{0}" will be replaced with the Field's value, and any occurrences of "{1}" will be replaced with the required date {@link Ext.form.field.Date#format format}.
83 The following code demonstrates placing the error message directly under the Field, and customizing the error message text:
84
85     {
86         xtype: 'datefield',
87         fieldLabel: 'Date of Birth',
88         name: 'birthDate',
89         msgTarget: 'under', // location of the error message
90         invalidText: '"{0}" bad. "{1}" good.' // custom error message text
91     }
92
93 {@img custom_error_message.png Custom Error Message}
94
95 #### 2. Custom Validations
96
97 Some validation requirements cannot be met using the built-in validations. The simplest way to implement a custom validation is to use the {@link Ext.form.field.Text Text Field}'s {@link Ext.form.field.Text#regex regex} configuration to apply validation rules, and the {@link Ext.form.field.Text#maskRe maskRe} configuration to limit which characters can be typed into the field. Here's an example of a Text Field that validates a time.
98
99     {
100         fieldLabel: 'Last Login Time',
101         name: 'loginTime',
102         regex: /^([1-9]|1[0-9]):([0-5][0-9])(\s[a|p]m)$/i,
103         maskRe: /[\d\s:amp]/i,
104         invalidText: 'Not a valid time.  Must be in the format "12:34 PM".'
105     }
106
107 While the above method works well for validating a single field, it is not practical for an application that has many fields that share the same custom validation.
108 The {@link Ext.form.field.VTypes} class provides a solution for creating reusable custom validations. Here's how a custom "time" validator can be created:
109
110     // custom Vtype for vtype:'time'
111     var timeTest = /^([1-9]|1[0-9]):([0-5][0-9])(\s[a|p]m)$/i;
112     Ext.apply(Ext.form.field.VTypes, {
113         //  vtype validation function
114         time: function(val, field) {
115             return timeTest.test(val);
116         },
117         // vtype Text property: The error text to display when the validation function returns false
118         timeText: 'Not a valid time.  Must be in the format "12:34 PM".',
119         // vtype Mask property: The keystroke filter mask
120         timeMask: /[\d\s:amp]/i
121     });
122
123 Once a custom validator has been created it can be used on Text Fields throughout an application using the `{@link Ext.form.field.Text#vtype vtype}` configuration:
124
125     {
126         fieldLabel: 'Last Login Time',
127         name: 'loginTime',
128         vtype: 'time'
129     }
130
131 See [Validation Example](guides/forms/examples/validation) for a working demo. For more information on custom validations please refer to the API Documentation for {@link Ext.form.field.VTypes VTypes}.
132
133 ## Handling Data
134
135 ### Submitting a Form
136
137 The simplest way to submit data to the server is to use the {@link Ext.form.Basic#url url} configuration of {@link Ext.form.Basic Basic Form}. Since {@link Ext.form.Panel Form Panel} wraps a Basic Form, we can use any of Basic Form's configuration options directly on a Form Panel:
138
139
140     Ext.create('Ext.form.Panel', {
141         ...
142         url: 'add_user',
143         items: [
144             ...
145         ]
146     });
147
148 The Basic Form's {@link Ext.form.Basic#submit submit} method can be used to submit data to the configured `url`:
149
150     Ext.create('Ext.form.Panel', {
151         ...
152         url: 'add_user',
153         items: [
154             ...
155         ],
156         buttons: [
157             {
158                 text: 'Submit',
159                 handler: function() {
160                     var form = this.up('form').getForm(); // get the basic form
161                     if (form.isValid()) { // make sure the form contains valid data before submitting
162                         form.submit({
163                             success: function(form, action) {
164                                Ext.Msg.alert('Success', action.result.msg);
165                             },
166                             failure: function(form, action) {
167                                 Ext.Msg.alert('Failed', action.result.msg);
168                             }
169                         });
170                     } else { // display error alert if the data is invalid
171                         Ext.Msg.alert('Invalid Data', 'Please correct form errors.')
172                     }
173                 }
174             }
175         ]
176     });
177
178 In the above example a button is configured with a handler that handles form submission. The handler takes the following actions:
179
180 1. First a reference to the Basic Form must be acquired.
181 2. Then the {@link Ext.form.Basic#isValid isValid} method is called before submission to verify that none of the fields have validation errors.
182 3. Finally the `submit` method is called, and two callback functions are passed - `success` and `failure`.  Within these callback functions `action.result` refers to the parsed JSON response.
183
184 The above example expects a JSON response that looks something like this:
185
186     { "success": true, "msg": "User added successfully" }
187
188 [Form Submission Example](guides/forms/examples/submit/index.html)
189
190 ### Binding a Form to a Model
191
192 The {@link Ext.data.Model Model} class is used throughout Ext JS for representing various types of data, as well as retrieving and updating data on the server.
193 A Model representing a User would define the fields a User has, as well as a proxy for loading and saving data:
194
195     Ext.define('User', {
196         extend: 'Ext.data.Model',
197         fields: ['firstName', 'lastName', 'birthDate'],
198         proxy: {
199             type: 'ajax',
200             api: {
201                 read: 'data/get_user',
202                 update: 'data/update_user'
203             },
204             reader: {
205                 type: 'json',
206                 root: 'users'
207             }
208         }
209     });
210
211 For more details on working with Models please refer to the [Data Guide](#/guide/data).
212
213 Data can be loaded into a {@link Ext.form.Panel Form Panel} directly from a {@link Ext.data.Model Model} using the {@link Ext.form.Panel#loadRecord loadRecord} method:
214
215     Ext.ModelMgr.getModel('User').load(1, { // load user with ID of "1"
216         success: function(user) {
217             userForm.loadRecord(user); // when user is loaded successfully, load the data into the form
218         }
219     });
220
221 Finally, instead of using the {@link Ext.form.Basic#submit submit} method to save the data, Basic Form's {@link Ext.form.Basic#updateRecord updateRecord} method is used to update the record with the form data, and the Model's {@link Ext.data.Model#save save} method is called to save the data to the server:
222
223     Ext.create('Ext.form.Panel', {
224         ...
225         url: 'add_user',
226         items: [
227             ...
228         ],
229         buttons: [
230             {
231                 text: 'Submit',
232                 handler: function() {
233                     var form = this.up('form').getForm(), // get the basic form
234                         record = form.getRecord(); // get the underlying model instance
235                     if (form.isValid()) { // make sure the form contains valid data before submitting
236                         form.updateRecord(record); // update the record with the form data
237                         record.save({ // save the record to the server
238                             success: function(user) {
239                                 Ext.Msg.alert('Success', 'User saved successfully.')
240                             },
241                             failure: function(user) {
242                                 Ext.Msg.alert('Failure', 'Failed to save user.')
243                             }
244                         });
245                     } else { // display error alert if the data is invalid
246                         Ext.Msg.alert('Invalid Data', 'Please correct form errors.')
247                     }
248                 }
249             }
250         ]
251     });
252
253 [Model Binding Example](guides/forms/examples/model_binding/index.html)
254
255 ## Layouts
256
257 Layouts are used to handle sizing and positioning of components in an Ext JS application.  {@link Ext.form.Panel Form Panels} can use any {@link Ext.layout.container.Container Container Layout}. For more information on Layouts please refer to the [Layouts and Containers Guide](#/guide/layouts_and_containers).
258
259 For example, positioning fields in a form horizontally can easily be done using an {@link Ext.layout.container.HBox HBox} Layout:
260
261     @example
262     Ext.create('Ext.form.Panel', {
263         renderTo: Ext.getBody(),
264         title: 'User Form',
265         height: 100,
266         width: 515,
267         defaults: {
268             xtype: 'textfield',
269             labelAlign: 'top',
270             padding: 10
271         },
272         layout: {
273             type: 'hbox'
274         },
275         items: [
276             {
277                 fieldLabel: 'First Name',
278                 name: 'firstName'
279             },
280             {
281                 fieldLabel: 'Last Name',
282                 name: 'lastName'
283             },
284             {
285                 xtype: 'datefield',
286                 fieldLabel: 'Date of Birth',
287                 name: 'birthDate'
288             }
289         ]
290     });
291
292 See the [Layout Example](guides/forms/examples/layout/index.html) for a live demo.