Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / Server.html
1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-data.proxy.Server'>/**
2 </span> * @author Ed Spencer
3  * @class Ext.data.proxy.Server
4  * @extends Ext.data.proxy.Proxy
5  * 
6  * &lt;p&gt;ServerProxy is a superclass of {@link Ext.data.proxy.JsonP JsonPProxy} and {@link Ext.data.proxy.Ajax AjaxProxy},
7  * and would not usually be used directly.&lt;/p&gt;
8  * 
9  * &lt;p&gt;ServerProxy should ideally be named HttpProxy as it is a superclass for all HTTP proxies - for Ext JS 4.x it has been 
10  * called ServerProxy to enable any 3.x applications that reference the HttpProxy to continue to work (HttpProxy is now an 
11  * alias of AjaxProxy).&lt;/p&gt;
12  */
13 Ext.define('Ext.data.proxy.Server', {
14     extend: 'Ext.data.proxy.Proxy',
15     alias : 'proxy.server',
16     alternateClassName: 'Ext.data.ServerProxy',
17     uses  : ['Ext.data.Request'],
18     
19 <span id='Ext-data.proxy.Server-cfg-url'>    /**
20 </span>     * @cfg {String} url The URL from which to request the data object.
21      */
22     
23 <span id='Ext-data.proxy.Server-cfg-reader'>    /**
24 </span>     * @cfg {Object/String/Ext.data.reader.Reader} reader The Ext.data.reader.Reader to use to decode the server's response. This can
25      * either be a Reader instance, a config object or just a valid Reader type name (e.g. 'json', 'xml').
26      */
27     
28 <span id='Ext-data.proxy.Server-cfg-writer'>    /**
29 </span>     * @cfg {Object/String/Ext.data.writer.Writer} writer The Ext.data.writer.Writer to use to encode any request sent to the server.
30      * This can either be a Writer instance, a config object or just a valid Writer type name (e.g. 'json', 'xml').
31      */
32     
33 <span id='Ext-data.proxy.Server-cfg-pageParam'>    /**
34 </span>     * @cfg {String} pageParam The name of the 'page' parameter to send in a request. Defaults to 'page'. Set this to
35      * undefined if you don't want to send a page parameter
36      */
37     pageParam: 'page',
38     
39 <span id='Ext-data.proxy.Server-cfg-startParam'>    /**
40 </span>     * @cfg {String} startParam The name of the 'start' parameter to send in a request. Defaults to 'start'. Set this
41      * to undefined if you don't want to send a start parameter
42      */
43     startParam: 'start',
44
45 <span id='Ext-data.proxy.Server-cfg-limitParam'>    /**
46 </span>     * @cfg {String} limitParam The name of the 'limit' parameter to send in a request. Defaults to 'limit'. Set this
47      * to undefined if you don't want to send a limit parameter
48      */
49     limitParam: 'limit',
50     
51 <span id='Ext-data.proxy.Server-cfg-groupParam'>    /**
52 </span>     * @cfg {String} groupParam The name of the 'group' parameter to send in a request. Defaults to 'group'. Set this
53      * to undefined if you don't want to send a group parameter
54      */
55     groupParam: 'group',
56     
57 <span id='Ext-data.proxy.Server-cfg-sortParam'>    /**
58 </span>     * @cfg {String} sortParam The name of the 'sort' parameter to send in a request. Defaults to 'sort'. Set this
59      * to undefined if you don't want to send a sort parameter
60      */
61     sortParam: 'sort',
62     
63 <span id='Ext-data.proxy.Server-cfg-filterParam'>    /**
64 </span>     * @cfg {String} filterParam The name of the 'filter' parameter to send in a request. Defaults to 'filter'. Set 
65      * this to undefined if you don't want to send a filter parameter
66      */
67     filterParam: 'filter',
68     
69 <span id='Ext-data.proxy.Server-cfg-directionParam'>    /**
70 </span>     * @cfg {String} directionParam The name of the direction parameter to send in a request. &lt;strong&gt;This is only used when simpleSortMode is set to true.&lt;/strong&gt;
71      * Defaults to 'dir'.
72      */
73     directionParam: 'dir',
74     
75 <span id='Ext-data.proxy.Server-cfg-simpleSortMode'>    /**
76 </span>     * @cfg {Boolean} simpleSortMode Enabling simpleSortMode in conjunction with remoteSort will only send one sort property and a direction when a remote sort is requested.
77      * The directionParam and sortParam will be sent with the property name and either 'ASC' or 'DESC'
78      */
79     simpleSortMode: false,
80     
81 <span id='Ext-data.proxy.Server-cfg-noCache'>    /**
82 </span>     * @cfg {Boolean} noCache (optional) Defaults to true. Disable caching by adding a unique parameter
83      * name to the request.
84      */
85     noCache : true,
86     
87 <span id='Ext-data.proxy.Server-cfg-cacheString'>    /**
88 </span>     * @cfg {String} cacheString The name of the cache param added to the url when using noCache (defaults to &quot;_dc&quot;)
89      */
90     cacheString: &quot;_dc&quot;,
91     
92 <span id='Ext-data.proxy.Server-cfg-timeout'>    /**
93 </span>     * @cfg {Number} timeout (optional) The number of milliseconds to wait for a response. Defaults to 30 seconds.
94      */
95     timeout : 30000,
96     
97 <span id='Ext-data.proxy.Server-cfg-api'>    /**
98 </span>     * @cfg {Object} api
99      * Specific urls to call on CRUD action methods &quot;read&quot;, &quot;create&quot;, &quot;update&quot; and &quot;destroy&quot;.
100      * Defaults to:&lt;pre&gt;&lt;code&gt;
101 api: {
102     read    : undefined,
103     create  : undefined,
104     update  : undefined,
105     destroy : undefined
106 }
107      * &lt;/code&gt;&lt;/pre&gt;
108      * &lt;p&gt;The url is built based upon the action being executed &lt;tt&gt;[load|create|save|destroy]&lt;/tt&gt;
109      * using the commensurate &lt;tt&gt;{@link #api}&lt;/tt&gt; property, or if undefined default to the
110      * configured {@link Ext.data.Store}.{@link Ext.data.proxy.Server#url url}.&lt;/p&gt;&lt;br&gt;
111      * &lt;p&gt;For example:&lt;/p&gt;
112      * &lt;pre&gt;&lt;code&gt;
113 api: {
114     load :    '/controller/load',
115     create :  '/controller/new',
116     save :    '/controller/update',
117     destroy : '/controller/destroy_action'
118 }
119      * &lt;/code&gt;&lt;/pre&gt;
120      * &lt;p&gt;If the specific URL for a given CRUD action is undefined, the CRUD action request
121      * will be directed to the configured &lt;tt&gt;{@link Ext.data.proxy.Server#url url}&lt;/tt&gt;.&lt;/p&gt;
122      */
123     
124 <span id='Ext-data.proxy.Server-method-constructor'>    /**
125 </span>     * @ignore
126      */
127     constructor: function(config) {
128         var me = this;
129         
130         config = config || {};
131         this.addEvents(
132 <span id='Ext-data.proxy.Server-event-exception'>            /**
133 </span>             * @event exception
134              * Fires when the server returns an exception
135              * @param {Ext.data.proxy.Proxy} this
136              * @param {Object} response The response from the AJAX request
137              * @param {Ext.data.Operation} operation The operation that triggered request
138              */
139             'exception'
140         );
141         me.callParent([config]);
142         
143 <span id='Ext-data.proxy.Server-cfg-extraParams'>        /**
144 </span>         * @cfg {Object} extraParams Extra parameters that will be included on every request. Individual requests with params
145          * of the same name will override these params when they are in conflict.
146          */
147         me.extraParams = config.extraParams || {};
148         
149         me.api = config.api || {};
150         
151         //backwards compatibility, will be deprecated in 5.0
152         me.nocache = me.noCache;
153     },
154     
155     //in a ServerProxy all four CRUD operations are executed in the same manner, so we delegate to doRequest in each case
156     create: function() {
157         return this.doRequest.apply(this, arguments);
158     },
159     
160     read: function() {
161         return this.doRequest.apply(this, arguments);
162     },
163     
164     update: function() {
165         return this.doRequest.apply(this, arguments);
166     },
167     
168     destroy: function() {
169         return this.doRequest.apply(this, arguments);
170     },
171     
172 <span id='Ext-data.proxy.Server-method-buildRequest'>    /**
173 </span>     * Creates and returns an Ext.data.Request object based on the options passed by the {@link Ext.data.Store Store}
174      * that this Proxy is attached to.
175      * @param {Ext.data.Operation} operation The {@link Ext.data.Operation Operation} object to execute
176      * @return {Ext.data.Request} The request object
177      */
178     buildRequest: function(operation) {
179         var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
180             request;
181         
182         //copy any sorters, filters etc into the params so they can be sent over the wire
183         params = Ext.applyIf(params, this.getParams(params, operation));
184         
185         if (operation.id &amp;&amp; !params.id) {
186             params.id = operation.id;
187         }
188         
189         request = Ext.create('Ext.data.Request', {
190             params   : params,
191             action   : operation.action,
192             records  : operation.records,
193             operation: operation,
194             url      : operation.url
195         });
196         
197         request.url = this.buildUrl(request);
198         
199         /*
200          * Save the request on the Operation. Operations don't usually care about Request and Response data, but in the
201          * ServerProxy and any of its subclasses we add both request and response as they may be useful for further processing
202          */
203         operation.request = request;
204         
205         return request;
206     },
207     
208 <span id='Ext-data.proxy.Server-method-processResponse'>    /**
209 </span>     * 
210      */
211     processResponse: function(success, operation, request, response, callback, scope){
212         var me = this,
213             reader,
214             result,
215             records,
216             length,
217             mc,
218             record,
219             i;
220             
221         if (success === true) {
222             reader = me.getReader();
223             result = reader.read(me.extractResponseData(response));
224             records = result.records;
225             length = records.length;
226             
227             if (result.success !== false) {
228                 mc = Ext.create('Ext.util.MixedCollection', true, function(r) {return r.getId();});
229                 mc.addAll(operation.records);
230                 for (i = 0; i &lt; length; i++) {
231                     record = mc.get(records[i].getId());
232                     
233                     if (record) {
234                         record.beginEdit();
235                         record.set(record.data);
236                         record.endEdit(true);
237                     }
238                 }
239                 
240                 //see comment in buildRequest for why we include the response object here
241                 Ext.apply(operation, {
242                     response: response,
243                     resultSet: result
244                 });
245                 
246                 operation.setCompleted();
247                 operation.setSuccessful();
248             } else {
249                 operation.setException(result.message);
250                 me.fireEvent('exception', this, response, operation);
251             }
252         } else {
253             me.setException(operation, response);
254             me.fireEvent('exception', this, response, operation);              
255         }
256             
257         //this callback is the one that was passed to the 'read' or 'write' function above
258         if (typeof callback == 'function') {
259             callback.call(scope || me, operation);
260         }
261             
262         me.afterRequest(request, success);
263     },
264     
265 <span id='Ext-data.proxy.Server-method-setException'>    /**
266 </span>     * Sets up an exception on the operation
267      * @private
268      * @param {Ext.data.Operation} operation The operation
269      * @param {Object} response The response
270      */
271     setException: function(operation, response){
272         operation.setException({
273             status: response.status,
274             statusText: response.statusText
275         });     
276     },
277     
278 <span id='Ext-data.proxy.Server-method-extractResponseData'>    /**
279 </span>     * Template method to allow subclasses to specify how to get the response for the reader.
280      * @private
281      * @param {Object} response The server response
282      * @return {Mixed} The response data to be used by the reader
283      */
284     extractResponseData: function(response){
285         return response; 
286     },
287     
288 <span id='Ext-data.proxy.Server-method-applyEncoding'>    /**
289 </span>     * Encode any values being sent to the server. Can be overridden in subclasses.
290      * @private
291      * @param {Array} An array of sorters/filters.
292      * @return {Mixed} The encoded value
293      */
294     applyEncoding: function(value){
295         return Ext.encode(value);
296     },
297     
298 <span id='Ext-data.proxy.Server-method-encodeSorters'>    /**
299 </span>     * Encodes the array of {@link Ext.util.Sorter} objects into a string to be sent in the request url. By default, 
300      * this simply JSON-encodes the sorter data
301      * @param {Array} sorters The array of {@link Ext.util.Sorter Sorter} objects
302      * @return {String} The encoded sorters
303      */
304     encodeSorters: function(sorters) {
305         var min = [],
306             length = sorters.length,
307             i = 0;
308         
309         for (; i &lt; length; i++) {
310             min[i] = {
311                 property : sorters[i].property,
312                 direction: sorters[i].direction
313             };
314         }
315         return this.applyEncoding(min);
316         
317     },
318     
319 <span id='Ext-data.proxy.Server-method-encodeFilters'>    /**
320 </span>     * Encodes the array of {@link Ext.util.Filter} objects into a string to be sent in the request url. By default, 
321      * this simply JSON-encodes the filter data
322      * @param {Array} sorters The array of {@link Ext.util.Filter Filter} objects
323      * @return {String} The encoded filters
324      */
325     encodeFilters: function(filters) {
326         var min = [],
327             length = filters.length,
328             i = 0;
329         
330         for (; i &lt; length; i++) {
331             min[i] = {
332                 property: filters[i].property,
333                 value   : filters[i].value
334             };
335         }
336         return this.applyEncoding(min);
337     },
338     
339 <span id='Ext-data.proxy.Server-method-getParams'>    /**
340 </span>     * @private
341      * Copy any sorters, filters etc into the params so they can be sent over the wire
342      */
343     getParams: function(params, operation) {
344         params = params || {};
345         
346         var me             = this,
347             isDef          = Ext.isDefined,
348             groupers       = operation.groupers,
349             sorters        = operation.sorters,
350             filters        = operation.filters,
351             page           = operation.page,
352             start          = operation.start,
353             limit          = operation.limit,
354             
355             simpleSortMode = me.simpleSortMode,
356             
357             pageParam      = me.pageParam,
358             startParam     = me.startParam,
359             limitParam     = me.limitParam,
360             groupParam     = me.groupParam,
361             sortParam      = me.sortParam,
362             filterParam    = me.filterParam,
363             directionParam       = me.directionParam;
364         
365         if (pageParam &amp;&amp; isDef(page)) {
366             params[pageParam] = page;
367         }
368         
369         if (startParam &amp;&amp; isDef(start)) {
370             params[startParam] = start;
371         }
372         
373         if (limitParam &amp;&amp; isDef(limit)) {
374             params[limitParam] = limit;
375         }
376         
377         if (groupParam &amp;&amp; groupers &amp;&amp; groupers.length &gt; 0) {
378             // Grouper is a subclass of sorter, so we can just use the sorter method
379             params[groupParam] = me.encodeSorters(groupers);
380         }
381         
382         if (sortParam &amp;&amp; sorters &amp;&amp; sorters.length &gt; 0) {
383             if (simpleSortMode) {
384                 params[sortParam] = sorters[0].property;
385                 params[directionParam] = sorters[0].direction;
386             } else {
387                 params[sortParam] = me.encodeSorters(sorters);
388             }
389             
390         }
391         
392         if (filterParam &amp;&amp; filters &amp;&amp; filters.length &gt; 0) {
393             params[filterParam] = me.encodeFilters(filters);
394         }
395         
396         return params;
397     },
398     
399 <span id='Ext-data.proxy.Server-method-buildUrl'>    /**
400 </span>     * Generates a url based on a given Ext.data.Request object. By default, ServerProxy's buildUrl will
401      * add the cache-buster param to the end of the url. Subclasses may need to perform additional modifications
402      * to the url.
403      * @param {Ext.data.Request} request The request object
404      * @return {String} The url
405      */
406     buildUrl: function(request) {
407         var me = this,
408             url = me.getUrl(request);
409         
410         //&lt;debug&gt;
411         if (!url) {
412             Ext.Error.raise(&quot;You are using a ServerProxy but have not supplied it with a url.&quot;);
413         }
414         //&lt;/debug&gt;
415         
416         if (me.noCache) {
417             url = Ext.urlAppend(url, Ext.String.format(&quot;{0}={1}&quot;, me.cacheString, Ext.Date.now()));
418         }
419         
420         return url;
421     },
422     
423 <span id='Ext-data.proxy.Server-method-getUrl'>    /**
424 </span>     * Get the url for the request taking into account the order of priority,
425      * - The request
426      * - The api
427      * - The url
428      * @private
429      * @param {Ext.data.Request} request The request
430      * @return {String} The url
431      */
432     getUrl: function(request){
433         return request.url || this.api[request.action] || this.url;
434     },
435     
436 <span id='Ext-data.proxy.Server-method-doRequest'>    /**
437 </span>     * In ServerProxy subclasses, the {@link #create}, {@link #read}, {@link #update} and {@link #destroy} methods all pass
438      * through to doRequest. Each ServerProxy subclass must implement the doRequest method - see {@link Ext.data.proxy.JsonP}
439      * and {@link Ext.data.proxy.Ajax} for examples. This method carries the same signature as each of the methods that delegate to it.
440      * @param {Ext.data.Operation} operation The Ext.data.Operation object
441      * @param {Function} callback The callback function to call when the Operation has completed
442      * @param {Object} scope The scope in which to execute the callback
443      */
444     doRequest: function(operation, callback, scope) {
445         //&lt;debug&gt;
446         Ext.Error.raise(&quot;The doRequest function has not been implemented on your Ext.data.proxy.Server subclass. See src/data/ServerProxy.js for details&quot;);
447         //&lt;/debug&gt;
448     },
449     
450 <span id='Ext-data.proxy.Server-property-afterRequest'>    /**
451 </span>     * Optional callback function which can be used to clean up after a request has been completed.
452      * @param {Ext.data.Request} request The Request object
453      * @param {Boolean} success True if the request was successful
454      */
455     afterRequest: Ext.emptyFn,
456     
457     onDestroy: function() {
458         Ext.destroy(this.reader, this.writer);
459     }
460 });
461 </pre></pre></body></html>