/ext-4.1.0_b3/docs/source/BelongsTo.html
HTML | 311 lines | 290 code | 21 blank | 0 comment | 0 complexity | 233cc185715131e0ee7f96fca797d0f5 MD5 | raw file
1<!DOCTYPE html>
2<html>
3<head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
10 </style>
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14 }
15 </script>
16</head>
17<body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-data-association-BelongsTo'>/**
19</span> * @author Ed Spencer
20 * @class Ext.data.association.BelongsTo
21 *
22 * Represents a many to one association with another model. The owner model is expected to have
23 * a foreign key which references the primary key of the associated model:
24 *
25 * Ext.define('Category', {
26 * extend: 'Ext.data.Model',
27 * fields: [
28 * { name: 'id', type: 'int' },
29 * { name: 'name', type: 'string' }
30 * ]
31 * });
32 *
33 * Ext.define('Product', {
34 * extend: 'Ext.data.Model',
35 * fields: [
36 * { name: 'id', type: 'int' },
37 * { name: 'category_id', type: 'int' },
38 * { name: 'name', type: 'string' }
39 * ],
40 * // we can use the belongsTo shortcut on the model to create a belongsTo association
41 * associations: [
42 * { type: 'belongsTo', model: 'Category' }
43 * ]
44 * });
45 *
46 * In the example above we have created models for Products and Categories, and linked them together
47 * by saying that each Product belongs to a Category. This automatically links each Product to a Category
48 * based on the Product's category_id, and provides new functions on the Product model:
49 *
50 * ## Generated getter function
51 *
52 * The first function that is added to the owner model is a getter function:
53 *
54 * var product = new Product({
55 * id: 100,
56 * category_id: 20,
57 * name: 'Sneakers'
58 * });
59 *
60 * product.getCategory(function(category, operation) {
61 * // do something with the category object
62 * alert(category.get('id')); // alerts 20
63 * }, this);
64 *
65 * The getCategory function was created on the Product model when we defined the association. This uses the
66 * Category's configured {@link Ext.data.proxy.Proxy proxy} to load the Category asynchronously, calling the provided
67 * callback when it has loaded.
68 *
69 * The new getCategory function will also accept an object containing success, failure and callback properties
70 * - callback will always be called, success will only be called if the associated model was loaded successfully
71 * and failure will only be called if the associatied model could not be loaded:
72 *
73 * product.getCategory({
74 * reload: true, // force a reload if the owner model is already cached
75 * callback: function(category, operation) {}, // a function that will always be called
76 * success : function(category, operation) {}, // a function that will only be called if the load succeeded
77 * failure : function(category, operation) {}, // a function that will only be called if the load did not succeed
78 * scope : this // optionally pass in a scope object to execute the callbacks in
79 * });
80 *
81 * In each case above the callbacks are called with two arguments - the associated model instance and the
82 * {@link Ext.data.Operation operation} object that was executed to load that instance. The Operation object is
83 * useful when the instance could not be loaded.
84 *
85 * Once the getter has been called on the model, it will be cached if the getter is called a second time. To
86 * force the model to reload, specify reload: true in the options object.
87 *
88 * ## Generated setter function
89 *
90 * The second generated function sets the associated model instance - if only a single argument is passed to
91 * the setter then the following two calls are identical:
92 *
93 * // this call...
94 * product.setCategory(10);
95 *
96 * // is equivalent to this call:
97 * product.set('category_id', 10);
98 *
99 * An instance of the owner model can also be passed as a parameter.
100 *
101 * If we pass in a second argument, the model will be automatically saved and the second argument passed to
102 * the owner model's {@link Ext.data.Model#save save} method:
103 *
104 * product.setCategory(10, function(product, operation) {
105 * // the product has been saved
106 * alert(product.get('category_id')); //now alerts 10
107 * });
108 *
109 * //alternative syntax:
110 * product.setCategory(10, {
111 * callback: function(product, operation), // a function that will always be called
112 * success : function(product, operation), // a function that will only be called if the load succeeded
113 * failure : function(product, operation), // a function that will only be called if the load did not succeed
114 * scope : this //optionally pass in a scope object to execute the callbacks in
115 * })
116 *
117 * ## Customisation
118 *
119 * Associations reflect on the models they are linking to automatically set up properties such as the
120 * {@link #primaryKey} and {@link #foreignKey}. These can alternatively be specified:
121 *
122 * Ext.define('Product', {
123 * fields: [...],
124 *
125 * associations: [
126 * { type: 'belongsTo', model: 'Category', primaryKey: 'unique_id', foreignKey: 'cat_id' }
127 * ]
128 * });
129 *
130 * Here we replaced the default primary key (defaults to 'id') and foreign key (calculated as 'category_id')
131 * with our own settings. Usually this will not be needed.
132 */
133Ext.define('Ext.data.association.BelongsTo', {
134 extend: 'Ext.data.association.Association',
135 alternateClassName: 'Ext.data.BelongsToAssociation',
136 alias: 'association.belongsto',
137
138<span id='Ext-data-association-BelongsTo-cfg-foreignKey'> /**
139</span> * @cfg {String} foreignKey The name of the foreign key on the owner model that links it to the associated
140 * model. Defaults to the lowercased name of the associated model plus "_id", e.g. an association with a
141 * model called Product would set up a product_id foreign key.
142 *
143 * Ext.define('Order', {
144 * extend: 'Ext.data.Model',
145 * fields: ['id', 'date'],
146 * hasMany: 'Product'
147 * });
148 *
149 * Ext.define('Product', {
150 * extend: 'Ext.data.Model',
151 * fields: ['id', 'name', 'order_id'], // refers to the id of the order that this product belongs to
152 * belongsTo: 'Group'
153 * });
154 * var product = new Product({
155 * id: 1,
156 * name: 'Product 1',
157 * order_id: 22
158 * }, 1);
159 * product.getOrder(); // Will make a call to the server asking for order_id 22
160 *
161 */
162
163<span id='Ext-data-association-BelongsTo-cfg-getterName'> /**
164</span> * @cfg {String} getterName The name of the getter function that will be added to the local model's prototype.
165 * Defaults to 'get' + the name of the foreign model, e.g. getCategory
166 */
167
168<span id='Ext-data-association-BelongsTo-cfg-setterName'> /**
169</span> * @cfg {String} setterName The name of the setter function that will be added to the local model's prototype.
170 * Defaults to 'set' + the name of the foreign model, e.g. setCategory
171 */
172
173<span id='Ext-data-association-BelongsTo-cfg-type'> /**
174</span> * @cfg {String} type The type configuration can be used when creating associations using a configuration object.
175 * Use 'belongsTo' to create a BelongsTo association.
176 *
177 * associations: [{
178 * type: 'belongsTo',
179 * model: 'User'
180 * }]
181 */
182 constructor: function(config) {
183 this.callParent(arguments);
184
185 var me = this,
186 ownerProto = me.ownerModel.prototype,
187 associatedName = me.associatedName,
188 getterName = me.getterName || 'get' + associatedName,
189 setterName = me.setterName || 'set' + associatedName;
190
191 Ext.applyIf(me, {
192 name : associatedName,
193 foreignKey : associatedName.toLowerCase() + "_id",
194 instanceName: associatedName + 'BelongsToInstance',
195 associationKey: associatedName.toLowerCase()
196 });
197
198 ownerProto[getterName] = me.createGetter();
199 ownerProto[setterName] = me.createSetter();
200 },
201
202<span id='Ext-data-association-BelongsTo-method-createSetter'> /**
203</span> * @private
204 * Returns a setter function to be placed on the owner model's prototype
205 * @return {Function} The setter function
206 */
207 createSetter: function() {
208 var me = this,
209 foreignKey = me.foreignKey;
210
211 //'this' refers to the Model instance inside this function
212 return function(value, options, scope) {
213 // If we pass in an instance, pull the id out
214 if (value && value.isModel) {
215 value = value.getId();
216 }
217 this.set(foreignKey, value);
218
219 if (Ext.isFunction(options)) {
220 options = {
221 callback: options,
222 scope: scope || this
223 };
224 }
225
226 if (Ext.isObject(options)) {
227 return this.save(options);
228 }
229 };
230 },
231
232<span id='Ext-data-association-BelongsTo-method-createGetter'> /**
233</span> * @private
234 * Returns a getter function to be placed on the owner model's prototype. We cache the loaded instance
235 * the first time it is loaded so that subsequent calls to the getter always receive the same reference.
236 * @return {Function} The getter function
237 */
238 createGetter: function() {
239 var me = this,
240 associatedName = me.associatedName,
241 associatedModel = me.associatedModel,
242 foreignKey = me.foreignKey,
243 primaryKey = me.primaryKey,
244 instanceName = me.instanceName;
245
246 //'this' refers to the Model instance inside this function
247 return function(options, scope) {
248 options = options || {};
249
250 var model = this,
251 foreignKeyId = model.get(foreignKey),
252 success,
253 instance,
254 args;
255
256 if (options.reload === true || model[instanceName] === undefined) {
257 instance = Ext.ModelManager.create({}, associatedName);
258 instance.set(primaryKey, foreignKeyId);
259
260 if (typeof options == 'function') {
261 options = {
262 callback: options,
263 scope: scope || model
264 };
265 }
266
267 // Overwrite the success handler so we can assign the current instance
268 success = options.success;
269 options.success = function(rec){
270 model[instanceName] = rec;
271 if (success) {
272 success.apply(this, arguments);
273 }
274 };
275
276 associatedModel.load(foreignKeyId, options);
277 // assign temporarily while we wait for data to return
278 model[instanceName] = instance;
279 return instance;
280 } else {
281 instance = model[instanceName];
282 args = [instance];
283 scope = scope || options.scope || model;
284
285 //TODO: We're duplicating the callback invokation code that the instance.load() call above
286 //makes here - ought to be able to normalize this - perhaps by caching at the Model.load layer
287 //instead of the association layer.
288 Ext.callback(options, scope, args);
289 Ext.callback(options.success, scope, args);
290 Ext.callback(options.failure, scope, args);
291 Ext.callback(options.callback, scope, args);
292
293 return instance;
294 }
295 };
296 },
297
298<span id='Ext-data-association-BelongsTo-method-read'> /**
299</span> * Read associated data
300 * @private
301 * @param {Ext.data.Model} record The record we're writing to
302 * @param {Ext.data.reader.Reader} reader The reader for the associated model
303 * @param {Object} associationData The raw associated data
304 */
305 read: function(record, reader, associationData){
306 record[this.instanceName] = reader.read([associationData]).records[0];
307 }
308});
309</pre>
310</body>
311</html>