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.
18 * Fields are used to define what a Model is. They aren't instantiated directly - instead, when we create a class that
19 * extends {@link Ext.data.Model}, it will automatically create a Field instance for each field configured in a {@link
20 * Ext.data.Model Model}. For example, we might set up a model like this:
22 * Ext.define('User', {
23 * extend: 'Ext.data.Model',
26 * {name: 'age', type: 'int'},
27 * {name: 'gender', type: 'string', defaultValue: 'Unknown'}
31 * Four fields will have been created for the User Model - name, email, age and gender. Note that we specified a couple
32 * of different formats here; if we only pass in the string name of the field (as with name and email), the field is set
33 * up with the 'auto' type. It's as if we'd done this instead:
35 * Ext.define('User', {
36 * extend: 'Ext.data.Model',
38 * {name: 'name', type: 'auto'},
39 * {name: 'email', type: 'auto'},
40 * {name: 'age', type: 'int'},
41 * {name: 'gender', type: 'string', defaultValue: 'Unknown'}
45 * # Types and conversion
47 * The {@link #type} is important - it's used to automatically convert data passed to the field into the correct format.
48 * In our example above, the name and email fields used the 'auto' type and will just accept anything that is passed
49 * into them. The 'age' field had an 'int' type however, so if we passed 25.4 this would be rounded to 25.
51 * Sometimes a simple type isn't enough, or we want to perform some processing when we load a Field's data. We can do
52 * this using a {@link #convert} function. Here, we're going to create a new field based on another:
54 * Ext.define('User', {
55 * extend: 'Ext.data.Model',
58 * {name: 'age', type: 'int'},
59 * {name: 'gender', type: 'string', defaultValue: 'Unknown'},
63 * convert: function(value, record) {
64 * var fullName = record.get('name'),
65 * splits = fullName.split(" "),
66 * firstName = splits[0];
74 * Now when we create a new User, the firstName is populated automatically based on the name:
76 * var ed = Ext.create('User', {name: 'Ed Spencer'});
78 * console.log(ed.get('firstName')); //logs 'Ed', based on our convert function
80 * In fact, if we log out all of the data inside ed, we'll see this:
82 * console.log(ed.data);
93 * The age field has been given a default of zero because we made it an int type. As an auto field, email has defaulted
94 * to an empty string. When we registered the User model we set gender's {@link #defaultValue} to 'Unknown' so we see
95 * that now. Let's correct that and satisfy ourselves that the types work as we expect:
97 * ed.set('gender', 'Male');
98 * ed.get('gender'); //returns 'Male'
100 * ed.set('age', 25.4);
101 * ed.get('age'); //returns 25 - we wanted an int, not a float, so no decimal places allowed
103 Ext.define('Ext.data.Field', {
104 requires: ['Ext.data.Types', 'Ext.data.SortTypes'],
107 constructor : function(config) {
108 if (Ext.isString(config)) {
109 config = {name: config};
111 Ext.apply(this, config);
113 var types = Ext.data.Types,
118 if (Ext.isString(this.type)) {
119 this.type = types[this.type.toUpperCase()] || types.AUTO;
122 this.type = types.AUTO;
125 // named sortTypes are supported, here we look them up
126 if (Ext.isString(st)) {
127 this.sortType = Ext.data.SortTypes[st];
128 } else if(Ext.isEmpty(st)) {
129 this.sortType = this.type.sortType;
133 this.convert = this.type.convert;
140 * The name by which the field is referenced within the Model. This is referenced by, for example, the `dataIndex`
141 * property in column definition objects passed to {@link Ext.grid.property.HeaderContainer}.
143 * Note: In the simplest case, if no properties other than `name` are required, a field definition may consist of
144 * just a String for the field name.
148 * @cfg {String/Object} type
150 * The data type for automatic conversion from received data to the *stored* value if
151 * `{@link Ext.data.Field#convert convert}` has not been specified. This may be specified as a string value.
152 * Possible values are
154 * - auto (Default, implies no conversion)
161 * This may also be specified by referencing a member of the {@link Ext.data.Types} class.
163 * Developers may create their own application-specific data types by defining new members of the {@link
164 * Ext.data.Types} class.
168 * @cfg {Function} convert
170 * A function which converts the value provided by the Reader into an object that will be stored in the Model.
171 * It is passed the following parameters:
175 * The data value as read by the Reader, if undefined will use the configured `{@link Ext.data.Field#defaultValue
178 * - **rec** : Ext.data.Model
180 * The data object containing the Model as read so far by the Reader. Note that the Model may not be fully populated
181 * at this point as the fields are read in the order that they are defined in your
182 * {@link Ext.data.Model#fields fields} array.
184 * Example of convert functions:
186 * function fullName(v, record){
187 * return record.name.last + ', ' + record.name.first;
190 * function location(v, record){
191 * return !record.city ? '' : (record.city + ', ' + record.state);
194 * Ext.define('Dude', {
195 * extend: 'Ext.data.Model',
197 * {name: 'fullname', convert: fullName},
198 * {name: 'firstname', mapping: 'name.first'},
199 * {name: 'lastname', mapping: 'name.last'},
200 * {name: 'city', defaultValue: 'homeless'},
202 * {name: 'location', convert: location}
206 * // create the data store
207 * var store = Ext.create('Ext.data.Store', {
213 * totalProperty: 'total'
219 * name: { first: 'Fat', last: 'Albert' }
220 * // notice no city, state provided in data object
223 * name: { first: 'Barney', last: 'Rubble' },
224 * city: 'Bedrock', state: 'Stoneridge'
227 * name: { first: 'Cliff', last: 'Claven' },
228 * city: 'Boston', state: 'MA'
234 * @cfg {String} dateFormat
236 * Used when converting received data into a Date when the {@link #type} is specified as `"date"`.
238 * A format string for the {@link Ext.Date#parse Ext.Date.parse} function, or "timestamp" if the value provided by
239 * the Reader is a UNIX timestamp, or "time" if the value provided by the Reader is a javascript millisecond
240 * timestamp. See {@link Ext.Date}.
245 * @cfg {Boolean} useNull
247 * Use when converting received data into a Number type (either int or float). If the value cannot be
248 * parsed, null will be used if useNull is true, otherwise the value will be 0. Defaults to false.
253 * @cfg {Object} defaultValue
255 * The default value used **when a Model is being created by a {@link Ext.data.reader.Reader Reader}**
256 * when the item referenced by the `{@link Ext.data.Field#mapping mapping}` does not exist in the data object
257 * (i.e. undefined). Defaults to "".
262 * @cfg {String/Number} mapping
264 * (Optional) A path expression for use by the {@link Ext.data.reader.Reader} implementation that is creating the
265 * {@link Ext.data.Model Model} to extract the Field value from the data object. If the path expression is the same
266 * as the field name, the mapping may be omitted.
268 * The form of the mapping expression depends on the Reader being used.
270 * - {@link Ext.data.reader.Json}
272 * The mapping is a string containing the javascript expression to reference the data from an element of the data
273 * item's {@link Ext.data.reader.Json#root root} Array. Defaults to the field name.
275 * - {@link Ext.data.reader.Xml}
277 * The mapping is an {@link Ext.DomQuery} path to the data item relative to the DOM element that represents the
278 * {@link Ext.data.reader.Xml#record record}. Defaults to the field name.
280 * - {@link Ext.data.reader.Array}
282 * The mapping is a number indicating the Array index of the field's value. Defaults to the field specification's
285 * If a more complex value extraction strategy is required, then configure the Field with a {@link #convert}
286 * function. This is passed the whole row object, and may interrogate it in whatever way is necessary in order to
287 * return the desired data.
292 * @cfg {Function} sortType
294 * A function which converts a Field's value to a comparable value in order to ensure correct sort ordering.
295 * Predefined functions are provided in {@link Ext.data.SortTypes}. A custom sort example:
297 * // current sort after sort we want
298 * // +-+------+ +-+------+
299 * // |1|First | |1|First |
300 * // |2|Last | |3|Second|
301 * // |3|Second| |2|Last |
302 * // +-+------+ +-+------+
304 * sortType: function(value) {
305 * switch (value.toLowerCase()) // native toLowerCase():
307 * case 'first': return 1;
308 * case 'second': return 2;
316 * @cfg {String} sortDir
318 * Initial direction to sort (`"ASC"` or `"DESC"`). Defaults to `"ASC"`.
323 * @cfg {Boolean} allowBlank
326 * Used for validating a {@link Ext.data.Model model}. Defaults to true. An empty value here will cause
327 * {@link Ext.data.Model}.{@link Ext.data.Model#isValid isValid} to evaluate to false.
332 * @cfg {Boolean} persist
334 * False to exclude this field from the {@link Ext.data.Model#modified} fields in a model. This will also exclude
335 * the field from being written using a {@link Ext.data.writer.Writer}. This option is useful when model fields are
336 * used to keep state on the client but do not need to be persisted to the server. Defaults to true.