Clear Up
SharpKit Reference

Ext.data.proxy Namespace

Download SDK: SharpKit.ExtJs.zip

Classes

Name Description
Ajax

AjaxProxy is one of the most widely-used ways of getting data into your application. It uses AJAX requests to load data from the server, usually to be placed into a Store. Let's take a look at a typical setup. Here we're going to set up a Store that has an AjaxProxy. To prepare, we'll also set up a Model:

  
    Ext.define('User', {
            extend: 'Ext.data.Model',
            fields: ['id', 'name', 'email']
            });
            //The Store contains the AjaxProxy as an inline configuration
            var store = Ext.create('Ext.data.Store', {
            model: 'User',
            proxy: {
            type: 'ajax',
            url : 'users.json'
            }
            });
            store.load();
            

Our example is going to load user data into a Store, so we start off by defining a Model with the fields that we expect the server to return. Next we set up the Store itself, along with a proxy configuration. This configuration was automatically turned into an Ext.data.proxy.Ajax instance, with the url we specified being passed into AjaxProxy's constructor. It's as if we'd done this:

  
new Ext.data.proxy.Ajax({
            url: 'users.json',
            model: 'User',
            reader: 'json'
            });
            

A couple of extra configurations appeared here - model and reader. These are set by default when we create the proxy via the Store - the Store already knows about the Model, and Proxy's default Reader is JsonReader.

Now when we call store.load(), the AjaxProxy springs into action, making a request to the url we configured ('users.json' in this case). As we're performing a read, it sends a GET request to that url (see actionMethods to customize this - by default any kind of read will be sent as a GET request and any kind of write will be sent as a POST request).

Limitations

AjaxProxy cannot be used to retrieve data from other domains. If your application is running on http://domainA.com it cannot load data from http://domainB.com because browsers have a built-in security policy that prohibits domains talking to each other via AJAX.

If you need to read data from another domain and can't set up a proxy server (some software that runs on your own domain's web server and transparently forwards requests to http://domainB.com, making it look like they actually came from http://domainA.com), you can use Ext.data.proxy.JsonP and a technique known as JSON-P (JSON with Padding), which can help you get around the problem so long as the server on http://domainB.com is set up to support JSON-P responses. See JsonPProxy's introduction docs for more details.

Readers and Writers

AjaxProxy can be configured to use any type of Reader to decode the server's response. If no Reader is supplied, AjaxProxy will default to using a JsonReader. Reader configuration can be passed in as a simple object, which the Proxy automatically turns into a Reader instance:

  
var proxy = new Ext.data.proxy.Ajax({
            model: 'User',
            reader: {
            type: 'xml',
            root: 'users'
            }
            });
            proxy.getReader(); //returns an XmlReader instance based on the config we supplied
            

Url generation

AjaxProxy automatically inserts any sorting, filtering, paging and grouping options into the url it generates for each request. These are controlled with the following configuration options:

  • pageParam - controls how the page number is sent to the server (see also startParam and limitParam)
  • sortParam - controls how sort information is sent to the server
  • groupParam - controls how grouping information is sent to the server
  • filterParam - controls how filter information is sent to the server

Each request sent by AjaxProxy is described by an Operation. To see how we can customize the generated urls, let's say we're loading the Proxy with the following Operation:

  
var operation = new Ext.data.Operation({
            action: 'read',
            page  : 2
            });
            

Now we'll issue the request for this Operation by calling read:

  
var proxy = new Ext.data.proxy.Ajax({
            url: '/users'
            });
            proxy.read(operation); //GET /users?page=2
            

Easy enough - the Proxy just copied the page property from the Operation. We can customize how this page data is sent to the server:

  
var proxy = new Ext.data.proxy.Ajax({
            url: '/users',
            pageParam: 'pageNumber'
            });
            proxy.read(operation); //GET /users?pageNumber=2
            

Alternatively, our Operation could have been configured to send start and limit parameters instead of page:

  
var operation = new Ext.data.Operation({
            action: 'read',
            start : 50,
            limit : 25
            });
            var proxy = new Ext.data.proxy.Ajax({
            url: '/users'
            });
            proxy.read(operation); //GET /users?start=50&limit;=25
            

Again we can customize this url:

  
var proxy = new Ext.data.proxy.Ajax({
            url: '/users',
            startParam: 'startIndex',
            limitParam: 'limitIndex'
            });
            proxy.read(operation); //GET /users?startIndex=50&limitIndex;=25
            

AjaxProxy will also send sort and filter information to the server. Let's take a look at how this looks with a more expressive Operation object:

  
var operation = new Ext.data.Operation({
            action: 'read',
            sorters: [
            new Ext.util.Sorter({
            property : 'name',
            direction: 'ASC'
            }),
            new Ext.util.Sorter({
            property : 'age',
            direction: 'DESC'
            })
            ],
            filters: [
            new Ext.util.Filter({
            property: 'eyeColor',
            value   : 'brown'
            })
            ]
            });
            

This is the type of object that is generated internally when loading a Store with sorters and filters defined. By default the AjaxProxy will JSON encode the sorters and filters, resulting in something like this (note that the url is escaped before sending the request, but is left unescaped here for clarity):

  
var proxy = new Ext.data.proxy.Ajax({
            url: '/users'
            });
            proxy.read(operation); //GET /users?sort=[{"property":"name","direction":"ASC"},{"property":"age","direction":"DESC"}]&filter;=[{"property":"eyeColor","value":"brown"}]
            

We can again customize how this is created by supplying a few configuration options. Let's say our server is set up to receive sorting information is a format like "sortBy=name#ASC,age#DESC". We can configure AjaxProxy to provide that format like this:

  
var proxy = new Ext.data.proxy.Ajax({
           url: '/users',
           sortParam: 'sortBy',
           filterParam: 'filterBy',
           //our custom implementation of sorter encoding - turns our sorters into "name#ASC,age#DESC"
           encodeSorters: function(sorters) {
           var length   = sorters.length,
           sortStrs = [],
           sorter, i;
           for (i = 0; i < length; i++) {
           sorter = sorters[i];
           sortStrs[i] = sorter.property + '#' + sorter.direction
           }
           return sortStrs.join(",");
           }
           });
           proxy.read(operation); //GET /users?sortBy=name#ASC,age#DESC&filterBy;=[{"property":"eyeColor","value":"brown"}]
            

We can also provide a custom encodeFilters function to encode our filters.

AjaxConfig
AjaxEvents
Client

NOTE This is a private utility class for internal use by the framework. Don't rely on its existence.

Base class for any client-side storage. Used as a superclass for Memory and Web Storage proxies. Do not use directly, use one of the subclasses instead.

ClientConfig
ClientEvents
Direct

This class is used to send requests to the server using Ext.Direct. When a request is made, the transport mechanism is handed off to the appropriate Provider to complete the call.

Specifying the function

This proxy expects a Direct remoting method to be passed in order to be able to complete requests. This can be done by specifying the directFn configuration. This will use the same direct method for all requests. Alternatively, you can provide an api configuration. This allows you to specify a different remoting method for each CRUD action.

Parameters

This proxy provides options to help configure which parameters will be sent to the server. By specifying the paramsAsHash option, it will send an object literal containing each of the passed parameters. The paramOrder option can be used to specify the order in which the remoting method parameters are passed.

Example Usage

  
    Ext.define('User', {
            extend: 'Ext.data.Model',
            fields: ['firstName', 'lastName'],
            proxy: {
            type: 'direct',
            directFn: MyApp.getUsers,
            paramOrder: 'id' // Tells the proxy to pass the id as the first parameter to the remoting method.
            }
            });
            User.load(1);
            
DirectConfig
DirectEvents
JsonP

The JsonP proxy is useful when you need to load data from a domain other than the one your application is running on. If your application is running on http://domainA.com it cannot use Ajax to load its data from http://domainB.com because cross-domain ajax requests are prohibited by the browser.

We can get around this using a JsonP proxy. JsonP proxy injects a <script> tag into the DOM whenever an AJAX request would usually be made. Let's say we want to load data from http://domainB.com/users - the script tag that would be injected might look like this:

  
<script src="http://domainB.com/users?callback=someCallback"></script>
            

When we inject the tag above, the browser makes a request to that url and includes the response as if it was any other type of JavaScript include. By passing a callback in the url above, we're telling domainB's server that we want to be notified when the result comes in and that it should call our callback function with the data it sends back. So long as the server formats the response to look like this, everything will work:

  
someCallback({
            users: [
            {
            id: 1,
            name: "Ed Spencer",
            email: "ed@sencha.com"
            }
            ]
            });
            

As soon as the script finishes loading, the 'someCallback' function that we passed in the url is called with the JSON object that the server returned.

JsonP proxy takes care of all of this automatically. It formats the url you pass, adding the callback parameter automatically. It even creates a temporary callback function, waits for it to be called and then puts the data into the Proxy making it look just like you loaded it through a normal AjaxProxy. Here's how we might set that up:

  
    Ext.define('User', {
            extend: 'Ext.data.Model',
            fields: ['id', 'name', 'email']
            });
            var store = Ext.create('Ext.data.Store', {
            model: 'User',
            proxy: {
            type: 'jsonp',
            url : 'http://domainB.com/users'
            }
            });
            store.load();
            

That's all we need to do - JsonP proxy takes care of the rest. In this case the Proxy will have injected a script tag like this:

  
<script src="http://domainB.com/users?callback=callback1"></script>
            

Customization

This script tag can be customized using the callbackKey configuration. For example:

  
var store = Ext.create('Ext.data.Store', {
            model: 'User',
            proxy: {
            type: 'jsonp',
            url : 'http://domainB.com/users',
            callbackKey: 'theCallbackFunction'
            }
            });
            store.load();
            

Would inject a script tag like this:

  
<script src="http://domainB.com/users?theCallbackFunction=callback1"></script>
            

Implementing on the server side

The remote server side needs to be configured to return data in this format. Here are suggestions for how you might achieve this using Java, PHP and ASP.net:

Java:

  
boolean jsonP = false;
            String cb = request.getParameter("callback");
            if (cb != null) {
            jsonP = true;
            response.setContentType("text/javascript");
            } else {
            response.setContentType("application/x-json");
            }
            Writer out = response.getWriter();
            if (jsonP) {
            out.write(cb + "(");
            }
            out.print(dataBlock.toJsonString());
            if (jsonP) {
            out.write(");");
            }
            

PHP:

  
$callback = $_REQUEST['callback'];
            // Create the output object.
            $output = array('a' => 'Apple', 'b' => 'Banana');
            //start output
            if ($callback) {
            header('Content-Type: text/javascript');
            echo $callback . '(' . json_encode($output) . ');';
            } else {
            header('Content-Type: application/x-json');
            echo json_encode($output);
            }
            

ASP.net:

  
String jsonString = "{success: true}";
            String cb = Request.Params.Get("callback");
            String responseString = "";
            if (!String.IsNullOrEmpty(cb)) {
            responseString = cb + "(" + jsonString + ")";
            } else {
            responseString = jsonString;
            }
            Response.Write(responseString);
            
JsonPConfig
JsonPEvents
LocalStorage

The LocalStorageProxy uses the new HTML5 localStorage API to save Model data locally on the client browser. HTML5 localStorage is a key-value store (e.g. cannot save complex objects like JSON), so LocalStorageProxy automatically serializes and deserializes data when saving and retrieving it.

localStorage is extremely useful for saving user-specific information without needing to build server-side infrastructure to support it. Let's imagine we're writing a Twitter search application and want to save the user's searches locally so they can easily perform a saved search again later. We'd start by creating a Search model:

  
    Ext.define('Search', {
            fields: ['id', 'query'],
            extend: 'Ext.data.Model',
            proxy: {
            type: 'localstorage',
            id  : 'twitter-Searches'
            }
            });
            

Our Search model contains just two fields - id and query - plus a Proxy definition. The only configuration we need to pass to the LocalStorage proxy is an id. This is important as it separates the Model data in this Proxy from all others. The localStorage API puts all data into a single shared namespace, so by setting an id we enable LocalStorageProxy to manage the saved Search data.

Saving our data into localStorage is easy and would usually be done with a Store:

  
//our Store automatically picks up the LocalStorageProxy defined on the Search model
            var store = Ext.create('Ext.data.Store', {
            model: "Search"
            });
            //loads any existing Search data from localStorage
            store.load();
            //now add some Searches
            store.add({query: 'Sencha Touch'});
            store.add({query: 'Ext JS'});
            //finally, save our Search data to localStorage
            store.sync();
            

The LocalStorageProxy automatically gives our new Searches an id when we call store.sync(). It encodes the Model data and places it into localStorage. We can also save directly to localStorage, bypassing the Store altogether:

  
var search = Ext.create('Search', {query: 'Sencha Animator'});
            //uses the configured LocalStorageProxy to save the new Search to localStorage
            search.save();
            

Limitations

If this proxy is used in a browser where local storage is not supported, the constructor will throw an error. A local storage proxy requires a unique ID which is used as a key in which all record data are stored in the local storage object.

It's important to supply this unique ID as it cannot be reliably determined otherwise. If no id is provided but the attached store has a storeId, the storeId will be used. If neither option is presented the proxy will throw an error.

LocalStorageConfig
LocalStorageEvents
Memory

In-memory proxy. This proxy simply uses a local variable for data storage/retrieval, so its contents are lost on every page refresh.

Usually this Proxy isn't used directly, serving instead as a helper to a Store where a reader is required to load data. For example, say we have a Store for a User model and have some inline data we want to load, but this data isn't in quite the right format: we can use a MemoryProxy with a JsonReader to read it into our Store:

  
//this is the model we will be using in the store
            Ext.define('User', {
            extend: 'Ext.data.Model',
            fields: [
            {name: 'id',    type: 'int'},
            {name: 'name',  type: 'string'},
            {name: 'phone', type: 'string', mapping: 'phoneNumber'}
            ]
            });
            //this data does not line up to our model fields - the phone field is called phoneNumber
            var data = {
            users: [
            {
            id: 1,
            name: 'Ed Spencer',
            phoneNumber: '555 1234'
            },
            {
            id: 2,
            name: 'Abe Elias',
            phoneNumber: '666 1234'
            }
            ]
            };
            //note how we set the 'root' in the reader to match the data structure above
            var store = Ext.create('Ext.data.Store', {
            autoLoad: true,
            model: 'User',
            data : data,
            proxy: {
            type: 'memory',
            reader: {
            type: 'json',
            root: 'users'
            }
            }
            });
            
MemoryConfig
MemoryEvents
Proxy

Proxies are used by Stores to handle the loading and saving of Model data. Usually developers will not need to create or interact with proxies directly.

Types of Proxy

There are two main types of Proxy - Client and Server. The Client proxies save their data locally and include the following subclasses:

  • LocalStorageProxy - saves its data to localStorage if the browser supports it
  • SessionStorageProxy - saves its data to sessionStorage if the browsers supports it
  • MemoryProxy - holds data in memory only, any data is lost when the page is refreshed

The Server proxies save their data by sending requests to some remote server. These proxies include:

  • Ajax - sends requests to a server on the same domain
  • JsonP - uses JSON-P to send requests to a server on a different domain
  • Rest - uses RESTful HTTP methods (GET/PUT/POST/DELETE) to communicate with server
  • Direct - uses Ext.direct.Manager to send requests

Proxies operate on the principle that all operations performed are either Create, Read, Update or Delete. These four operations are mapped to the methods create, read, update and destroy respectively. Each Proxy subclass implements these functions.

The CRUD methods each expect an Operation object as the sole argument. The Operation encapsulates information about the action the Store wishes to perform, the model instances that are to be modified, etc. See the Operation documentation for more details. Each CRUD method also accepts a callback function to be called asynchronously on completion.

Proxies also support batching of Operations via a batch object, invoked by the batch method.

ProxyConfig
ProxyEvents
Rest

The Rest proxy is a specialization of the AjaxProxy which simply maps the four actions (create, read, update and destroy) to RESTful HTTP verbs. For example, let's set up a Model with an inline Rest proxy

  
    Ext.define('User', {
            extend: 'Ext.data.Model',
            fields: ['id', 'name', 'email'],
            proxy: {
            type: 'rest',
            url : '/users'
            }
            });
            

Now we can create a new User instance and save it via the Rest proxy. Doing this will cause the Proxy to send a POST request to '/users':

  
var user = Ext.create('User', {name: 'Ed Spencer', email: 'ed@sencha.com'});
            user.save(); //POST /users
            

Let's expand this a little and provide a callback for the Ext.data.Model.save call to update the Model once it has been created. We'll assume the creation went successfully and that the server gave this user an ID of 123:

  
user.save({
            success: function(user) {
            user.set('name', 'Khan Noonien Singh');
            user.save(); //PUT /users/123
            }
            });
            

Now that we're no longer creating a new Model instance, the request method is changed to an HTTP PUT, targeting the relevant url for that user. Now let's delete this user, which will use the DELETE method:

  
user.destroy(); //DELETE /users/123
            

Finally, when we perform a load of a Model or Store, Rest proxy will use the GET method:

  
//1. Load via Store
            //the Store automatically picks up the Proxy from the User model
            var store = Ext.create('Ext.data.Store', {
            model: 'User'
            });
            store.load(); //GET /users
            //2. Load directly from the Model
            //GET /users/123
            Ext.ModelManager.getModel('User').load(123, {
            success: function(user) {
            console.log(user.getId()); //outputs 123
            }
            });
            

Url generation

The Rest proxy is able to automatically generate the urls above based on two configuration options - appendId and format. If appendId is true (it is by default) then Rest proxy will automatically append the ID of the Model instance in question to the configured url, resulting in the '/users/123' that we saw above.

If the request is not for a specific Model instance (e.g. loading a Store), the url is not appended with an id. The Rest proxy will automatically insert a '/' before the ID if one is not already present.

  
new Ext.data.proxy.Rest({
            url: '/users',
            appendId: true //default
            });
            // Collection url: /users
            // Instance url  : /users/123
            

The Rest proxy can also optionally append a format string to the end of any generated url:

  
new Ext.data.proxy.Rest({
            url: '/users',
            format: 'json'
            });
            // Collection url: /users.json
            // Instance url  : /users/123.json
            

If further customization is needed, simply implement the buildUrl method and add your custom generated url onto the Request object that is passed to buildUrl. See Rest proxy's implementation for an example of how to achieve this.

Note that Rest proxy inherits from AjaxProxy, which already injects all of the sorter, filter, group and paging options into the generated url. See the AjaxProxy docs for more details.

RestConfig
RestEvents
Server

NOTE This is a private utility class for internal use by the framework. Don't rely on its existence.

ServerProxy is a superclass of JsonPProxy and AjaxProxy, and would not usually be used directly.

ServerProxy should ideally be named HttpProxy as it is a superclass for all HTTP proxies - for Ext JS 4.x it has been called ServerProxy to enable any 3.x applications that reference the HttpProxy to continue to work (HttpProxy is now an alias of AjaxProxy).

ServerConfig
ServerEvents
SessionStorage

Proxy which uses HTML5 session storage as its data storage/retrieval mechanism. If this proxy is used in a browser where session storage is not supported, the constructor will throw an error. A session storage proxy requires a unique ID which is used as a key in which all record data are stored in the session storage object.

It's important to supply this unique ID as it cannot be reliably determined otherwise. If no id is provided but the attached store has a storeId, the storeId will be used. If neither option is presented the proxy will throw an error.

Proxies are almost always used with a store:

  
new Ext.data.Store({
            proxy: {
            type: 'sessionstorage',
            id  : 'myProxyKey'
            }
            });
            

Alternatively you can instantiate the Proxy directly:

  
new Ext.data.proxy.SessionStorage({
            id  : 'myOtherProxyKey'
            });
            

Note that session storage is different to local storage (see Ext.data.proxy.LocalStorage) - if a browser session is ended (e.g. by closing the browser) then all data in a SessionStorageProxy are lost. Browser restarts don't affect the Ext.data.proxy.LocalStorage - the data are preserved.

SessionStorageConfig
SessionStorageEvents
WebStorage

NOTE This is a private utility class for internal use by the framework. Don't rely on its existence.

WebStorageProxy is simply a superclass for the LocalStorage and SessionStorage proxies. It uses the new HTML5 key/value client-side storage objects to save model instances for offline use.

WebStorageConfig
WebStorageEvents
© Copyright 2005-2011 SharpKit. All rights reserved.