|
|
Ext.data Namespace
Download SDK: SharpKit.ExtJs.zip
Classes
|
AbstractStore
|
AbstractStore is a superclass of Ext.data.Store and Ext.data.TreeStore. It's never used directly,
but offers a set of methods used by both of those subclasses. We've left it here in the docs for reference purposes, but unless you need to make a whole new type of Store, what
you're probably looking for is Ext.data.Store. If you're still interested, here's a brief description of what
AbstractStore is and is not. AbstractStore provides the basic configuration for anything that can be considered a Store. It expects to be
given a Model that represents the type of data in the Store. It also expects to be given a
Proxy that handles the loading of data into the Store. AbstractStore provides a few helpful methods such as load and sync, which load and save data
respectively, passing the requests through the configured proxy. Both built-in Store subclasses add extra
behavior to each of these functions. Note also that each AbstractStore subclass has its own way of storing data -
in Ext.data.Store the data is saved as a flat MixedCollection, whereas in
TreeStore we use a Ext.data.Tree to maintain the data's hierarchy. The store provides filtering and sorting support. This sorting/filtering can happen on the client side
or can be completed on the server. This is controlled by the remoteSort and (@link #remoteFilter{ config
options. For more information see the sort and filter methods.
|
|
AbstractStoreConfig
|
|
|
AbstractStoreEvents
|
|
|
ArrayStore
|
Small helper class to make creating Ext.data.Stores from Array data easier. An ArrayStore will be
automatically configured with a Ext.data.reader.Array. A store configuration would be something like: var store = Ext.create('Ext.data.ArrayStore', {
// store configs
autoDestroy: true,
storeId: 'myStore',
// reader configs
idIndex: 0,
fields: [
'company',
{name: 'price', type: 'float'},
{name: 'change', type: 'float'},
{name: 'pctChange', type: 'float'},
{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
]
});
This store is configured to consume a returned object of the form: var myData = [
['3m Co',71.72,0.02,0.03,'9/1 12:00am'],
['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am'],
['Boeing Co.',75.43,0.53,0.71,'9/1 12:00am'],
['Hewlett-Packard Co.',36.53,-0.03,-0.08,'9/1 12:00am'],
['Wal-Mart Stores, Inc.',45.45,0.73,1.63,'9/1 12:00am']
];
An object literal of this form could also be used as the data config option. Note: Although not listed here, this class accepts all of the configuration options of
ArrayReader.
|
|
ArrayStoreConfig
|
|
|
ArrayStoreEvents
|
|
|
Association
|
Associations enable you to express relationships between different Models. Let's say we're
writing an ecommerce system where Users can make Orders - there's a relationship between these Models that we can
express like this: Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['id', 'name', 'email'],
hasMany: {model: 'Order', name: 'orders'}
});
Ext.define('Order', {
extend: 'Ext.data.Model',
fields: ['id', 'user_id', 'status', 'price'],
belongsTo: 'User'
});
We've set up two models - User and Order - and told them about each other. You can set up as many associations on
each Model as you need using the two default types - hasMany and
belongsTo. There's much more detail on the usage of each of those inside their
documentation pages. If you're not familiar with Models already, there is plenty on those too. Further Reading hasMany associations belongsTo associations using Models Self association models We can also have models that create parent/child associations between the same type. Below is an example, where
groups can be nested inside other groups:
// Server Data
{
"groups": {
"id": 10,
"parent_id": 100,
"name": "Main Group",
"parent_group": {
"id": 100,
"parent_id": null,
"name": "Parent Group"
},
"child_groups": [{
"id": 2,
"parent_id": 10,
"name": "Child Group 1"
},{
"id": 3,
"parent_id": 10,
"name": "Child Group 2"
},{
"id": 4,
"parent_id": 10,
"name": "Child Group 3"
}]
}
}
// Client code
Ext.define('Group', {
extend: 'Ext.data.Model',
fields: ['id', 'parent_id', 'name'],
proxy: {
type: 'ajax',
url: 'data.json',
reader: {
type: 'json',
root: 'groups'
}
},
associations: [{
type: 'hasMany',
model: 'Group',
primaryKey: 'id',
foreignKey: 'parent_id',
autoLoad: true,
associationKey: 'child_groups' // read child data from child_groups
}, {
type: 'belongsTo',
model: 'Group',
primaryKey: 'id',
foreignKey: 'parent_id',
autoLoad: true,
associationKey: 'parent_group' // read parent data from parent_group
}]
});
Ext.onReady(function(){
Group.load(10, {
success: function(group){
console.log(group.getGroup().get('name'));
group.groups().each(function(rec){
console.log(rec.get('name'));
});
}
});
});
|
|
AssociationConfig
|
|
|
AssociationEvents
|
|
|
Batch
|
Provides a mechanism to run one or more operations in a given order. Fires the 'operationcomplete' event
after the completion of each Operation, and the 'complete' event when all Operations have been successfully executed. Fires an 'exception'
event if any of the Operations encounter an exception. Usually these are only used internally by Ext.data.proxy.Proxy classes
|
|
BatchConfig
|
|
|
BatchEvents
|
|
|
BelongsToAssociation
|
Represents a many to one association with another model. The owner model is expected to have
a foreign key which references the primary key of the associated model: Ext.define('Category', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'}
]
});
Ext.define('Product', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'category_id', type: 'int'},
{name: 'name', type: 'string'}
],
// we can use the belongsTo shortcut on the model to create a belongsTo association
belongsTo: {type: 'belongsTo', model: 'Category'}
});
In the example above we have created models for Products and Categories, and linked them together
by saying that each Product belongs to a Category. This automatically links each Product to a Category
based on the Product's category_id, and provides new functions on the Product model: Generated getter function The first function that is added to the owner model is a getter function: var product = new Product({
id: 100,
category_id: 20,
name: 'Sneakers'
});
product.getCategory(function(category, operation) {
//do something with the category object
alert(category.get('id')); //alerts 20
}, this);
The getCategory function was created on the Product model when we defined the association. This uses the
Category's configured proxy to load the Category asynchronously, calling the provided
callback when it has loaded. The new getCategory function will also accept an object containing success, failure and callback properties
- callback will always be called, success will only be called if the associated model was loaded successfully
and failure will only be called if the associatied model could not be loaded: product.getCategory({
callback: function(category, operation) {}, //a function that will always be called
success : function(category, operation) {}, //a function that will only be called if the load succeeded
failure : function(category, operation) {}, //a function that will only be called if the load did not succeed
scope : this //optionally pass in a scope object to execute the callbacks in
});
In each case above the callbacks are called with two arguments - the associated model instance and the
operation object that was executed to load that instance. The Operation object is
useful when the instance could not be loaded. Generated setter function The second generated function sets the associated model instance - if only a single argument is passed to
the setter then the following two calls are identical: //this call
product.setCategory(10);
//is equivalent to this call:
product.set('category_id', 10);
If we pass in a second argument, the model will be automatically saved and the second argument passed to
the owner model's save method: product.setCategory(10, function(product, operation) {
//the product has been saved
alert(product.get('category_id')); //now alerts 10
});
//alternative syntax:
product.setCategory(10, {
callback: function(product, operation), //a function that will always be called
success : function(product, operation), //a function that will only be called if the load succeeded
failure : function(product, operation), //a function that will only be called if the load did not succeed
scope : this //optionally pass in a scope object to execute the callbacks in
})
Customisation Associations reflect on the models they are linking to automatically set up properties such as the
primaryKey and foreignKey. These can alternatively be specified: Ext.define('Product', {
fields: [...],
associations: [
{type: 'belongsTo', model: 'Category', primaryKey: 'unique_id', foreignKey: 'cat_id'}
]
});
Here we replaced the default primary key (defaults to 'id') and foreign key (calculated as 'category_id')
with our own settings. Usually this will not be needed.
|
|
BelongsToAssociationConfig
|
|
|
BelongsToAssociationEvents
|
|
|
Connection
|
The Connection class encapsulates a connection to the page's originating domain, allowing requests to be made either
to a configured URL, or to a URL specified at request time. Requests made by this class are asynchronous, and will return immediately. No data from the server will be available
to the statement immediately following the request call. To process returned data, use a success callback
in the request options object, or an event listener. File Uploads File uploads are not performed using normal "Ajax" techniques, that is they are not performed using XMLHttpRequests.
Instead the form is submitted in the standard manner with the DOM <form> element temporarily modified to have its
target set to refer to a dynamically generated, hidden <iframe> which is inserted into the document but removed
after the return data has been gathered. The server response is parsed by the browser to create the document for the IFRAME. If the server is using JSON to
send the return object, then the Content-Type header must be set to "text/html" in order to tell the browser to
insert the text unchanged into the document body. Characters which are significant to an HTML parser must be sent as HTML entities, so encode "<" as "&lt;", "&" as
"&amp;" etc. The response text is retrieved from the document, and a fake XMLHttpRequest object is created containing a
responseText property in order to conform to the requirements of event handlers and callbacks. Be aware that file upload packets are sent with the content type multipart/form and some server technologies
(notably JEE) may require some custom processing in order to retrieve parameter names and parameter values from the
packet content. Also note that it's not possible to check the response code of the hidden iframe, so the success handler will ALWAYS fire.
|
|
ConnectionConfig
|
|
|
ConnectionEvents
|
|
|
DirectStore
|
Small helper class to create an Ext.data.Store configured with an
Ext.data.proxy.Direct and Ext.data.reader.Json to make interacting
with an Ext.Direct Server-side Provider easier.
To create a different proxy/reader combination create a basic Ext.data.Store
configured as needed. *Note: Although they are not listed, this class inherits all of the config options of: Store JsonReader root idProperty totalProperty DirectProxy directFn paramOrder paramsAsHash
|
|
DirectStoreConfig
|
|
|
DirectStoreEvents
|
|
|
Errors
|
Wraps a collection of validation error responses and provides convenient functions for
accessing and errors for specific fields. Usually this class does not need to be instantiated directly - instances are instead created
automatically when validate on a model instance: //validate some existing model instance - in this case it returned 2 failures messages
var errors = myModel.validate();
errors.isValid(); //false
errors.length; //2
errors.getByField('name'); // [{field: 'name', message: 'must be present'}]
errors.getByField('title'); // [{field: 'title', message: 'is too short'}]
|
|
ErrorsConfig
|
|
|
ErrorsEvents
|
|
|
Field
|
Fields are used to define what a Model is. They aren't instantiated directly - instead, when we create a class
that extends Ext.data.Model, it will automatically create a Field instance for each field configured in a
Model. For example, we might set up a model like this: Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
'name', 'email',
{name: 'age', type: 'int'},
{name: 'gender', type: 'string', defaultValue: 'Unknown'}
]
});
Four fields will have been created for the User Model - name, email, age and gender. Note that we specified a
couple of different formats here; if we only pass in the string name of the field (as with name and email), the
field is set up with the 'auto' type. It's as if we'd done this instead: Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'auto'},
{name: 'email', type: 'auto'},
{name: 'age', type: 'int'},
{name: 'gender', type: 'string', defaultValue: 'Unknown'}
]
});
Types and conversion The type is important - it's used to automatically convert data passed to the field into the correct
format. In our example above, the name and email fields used the 'auto' type and will just accept anything that is
passed into them. The 'age' field had an 'int' type however, so if we passed 25.4 this would be rounded to 25. Sometimes a simple type isn't enough, or we want to perform some processing when we load a Field's data. We can
do this using a convert function. Here, we're going to create a new field based on another: Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
'name', 'email',
{name: 'age', type: 'int'},
{name: 'gender', type: 'string', defaultValue: 'Unknown'},
{
name: 'firstName',
convert: function(value, record) {
var fullName = record.get('name'),
splits = fullName.split(" "),
firstName = splits[0];
return firstName;
}
}
]
});
Now when we create a new User, the firstName is populated automatically based on the name: var ed = Ext.ModelManager.create({name: 'Ed Spencer'}, 'User');
console.log(ed.get('firstName')); //logs 'Ed', based on our convert function
In fact, if we log out all of the data inside ed, we'll see this: console.log(ed.data);
//outputs this:
{
age: 0,
email: "",
firstName: "Ed",
gender: "Unknown",
name: "Ed Spencer"
}
The age field has been given a default of zero because we made it an int type. As an auto field, email has
defaulted to an empty string. When we registered the User model we set gender's defaultValue to 'Unknown'
so we see that now. Let's correct that and satisfy ourselves that the types work as we expect: ed.set('gender', 'Male');
ed.get('gender'); //returns 'Male'
ed.set('age', 25.4);
ed.get('age'); //returns 25 - we wanted an int, not a float, so no decimal places allowed
|
|
FieldConfig
|
|
|
FieldEvents
|
|
|
HasManyAssociation
|
Represents a one-to-many relationship between two models. Usually created indirectly via a model definition: Ext.define('Product', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'user_id', type: 'int'},
{name: 'name', type: 'string'}
]
});
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'}
],
// we can use the hasMany shortcut on the model to create a hasMany association
hasMany: {model: 'Product', name: 'products'}
});
Above we created Product and User models, and linked them by saying that a User hasMany Products. This gives
us a new function on every User instance, in this case the function is called 'products' because that is the name
we specified in the association configuration above. This new function returns a specialized Store which is automatically filtered to load
only Products for the given model instance: //first, we load up a User with id of 1
var user = Ext.ModelManager.create({id: 1, name: 'Ed'}, 'User');
//the user.products function was created automatically by the association and returns a Store
//the created store is automatically scoped to the set of Products for the User with id of 1
var products = user.products();
//we still have all of the usual Store functions, for example it's easy to add a Product for this User
products.add({
name: 'Another Product'
});
//saves the changes to the store - this automatically sets the new Product's user_id to 1 before saving
products.sync();
The new Store is only instantiated the first time you call products() to conserve memory and processing time,
though calling products() a second time returns the same store instance. Custom filtering The Store is automatically furnished with a filter - by default this filter tells the store to only return
records where the associated model's foreign key matches the owner model's primary key. For example, if a User
with ID = 100 hasMany Products, the filter loads only Products with user_id == 100. Sometimes we want to filter by another field - for example in the case of a Twitter search application we may
have models for Search and Tweet: Ext.define('Search', {
extend: 'Ext.data.Model',
fields: [
'id', 'query'
],
hasMany: {
model: 'Tweet',
name : 'tweets',
filterProperty: 'query'
}
});
Ext.define('Tweet', {
extend: 'Ext.data.Model',
fields: [
'id', 'text', 'from_user'
]
});
//returns a Store filtered by the filterProperty
var store = new Search({query: 'Sencha Touch'}).tweets();
The tweets association above is filtered by the query property by setting the filterProperty, and is
equivalent to this: var store = new Ext.data.Store({
model: 'Tweet',
filters: [
{
property: 'query',
value : 'Sencha Touch'
}
]
});
|
|
HasManyAssociationConfig
|
|
|
HasManyAssociationEvents
|
|
|
JsonP
|
This class is used to create JSONP requests. JSONP is a mechanism that allows for making
requests for data cross domain. More information is available here:
http://en.wikipedia.org/wiki/JSONP
|
|
JsonPConfig
|
|
|
JsonPEvents
|
|
|
Model
|
A Model represents some object that your application manages. For example, one might define a Model for Users, Products,
Cars, or any other real-world object that we want to model in the system. Models are registered via the model manager,
and are used by stores, which are in turn used by many of the data-bound components in Ext. Models are defined as a set of fields and any arbitrary methods and properties relevant to the model. For example: Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'string'},
{name: 'age', type: 'int'},
{name: 'phone', type: 'string'},
{name: 'alive', type: 'boolean', defaultValue: true}
],
changeName: function() {
var oldName = this.get('name'),
newName = oldName + " The Barbarian";
this.set('name', newName);
}
});
The fields array is turned into a MixedCollection automatically by the ModelManager, and all
other functions and properties are copied to the new Model's prototype. Now we can create instances of our User model and call any model logic we defined: var user = Ext.ModelManager.create({
name : 'Conan',
age : 24,
phone: '555-555-5555'
}, 'User');
user.changeName();
user.get('name'); //returns "Conan The Barbarian"
Validations Models have built-in support for validations, which are executed against the validator functions in
Ext.data.validations (see all validation functions). Validations are easy to add to models: Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'string'},
{name: 'age', type: 'int'},
{name: 'phone', type: 'string'},
{name: 'gender', type: 'string'},
{name: 'username', type: 'string'},
{name: 'alive', type: 'boolean', defaultValue: true}
],
validations: [
{type: 'presence', field: 'age'},
{type: 'length', field: 'name', min: 2},
{type: 'inclusion', field: 'gender', list: ['Male', 'Female']},
{type: 'exclusion', field: 'username', list: ['Admin', 'Operator']},
{type: 'format', field: 'username', matcher: /([a-z]+)[0-9]{2,3}/}
]
});
The validations can be run by simply calling the validate function, which returns a Ext.data.Errors
object: var instance = Ext.ModelManager.create({
name: 'Ed',
gender: 'Male',
username: 'edspencer'
}, 'User');
var errors = instance.validate();
Associations Models can have associations with other Models via belongsTo and
hasMany associations. For example, let's say we're writing a blog administration
application which deals with Users, Posts and Comments. We can express the relationships between these models like this: Ext.define('Post', {
extend: 'Ext.data.Model',
fields: ['id', 'user_id'],
belongsTo: 'User',
hasMany : {model: 'Comment', name: 'comments'}
});
Ext.define('Comment', {
extend: 'Ext.data.Model',
fields: ['id', 'user_id', 'post_id'],
belongsTo: 'Post'
});
Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['id'],
hasMany: [
'Post',
{model: 'Comment', name: 'comments'}
]
});
See the docs for Ext.data.BelongsToAssociation and Ext.data.HasManyAssociation for details on the usage
and configuration of associations. Note that associations can also be specified like this: Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['id'],
associations: [
{type: 'hasMany', model: 'Post', name: 'posts'},
{type: 'hasMany', model: 'Comment', name: 'comments'}
]
});
Using a Proxy Models are great for representing types of data and relationships, but sooner or later we're going to want to
load or save that data somewhere. All loading and saving of data is handled via a Proxy,
which can be set directly on the Model: Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['id', 'name', 'email'],
proxy: {
type: 'rest',
url : '/users'
}
});
Here we've set up a Rest Proxy, which knows how to load and save data to and from a
RESTful backend. Let's see how this works: var user = Ext.ModelManager.create({name: 'Ed Spencer', email: 'ed@sencha.com'}, 'User');
user.save(); //POST /users
Calling save on the new Model instance tells the configured RestProxy that we wish to persist this
Model's data onto our server. RestProxy figures out that this Model hasn't been saved before because it doesn't
have an id, and performs the appropriate action - in this case issuing a POST request to the url we configured
(/users). We configure any Proxy on any Model and always follow this API - see Ext.data.proxy.Proxy for a full
list. Loading data via the Proxy is equally easy: //get a reference to the User model class
var User = Ext.ModelManager.getModel('User');
//Uses the configured RestProxy to make a GET request to /users/123
User.load(123, {
success: function(user) {
console.log(user.getId()); //logs 123
}
});
Models can also be updated and destroyed easily: //the user Model we loaded in the last snippet:
user.set('name', 'Edward Spencer');
//tells the Proxy to save the Model. In this case it will perform a PUT request to /users/123 as this Model already has an id
user.save({
success: function() {
console.log('The User was updated');
}
});
//tells the Proxy to destroy the Model. Performs a DELETE request to /users/123
user.destroy({
success: function() {
console.log('The User was destroyed!');
}
});
Usage in Stores It is very common to want to load a set of Model instances to be displayed and manipulated in the UI. We do this
by creating a Store: var store = new Ext.data.Store({
model: 'User'
});
//uses the Proxy we set up on Model to load the Store data
store.load();
A Store is just a collection of Model instances - usually loaded from a server somewhere. Store can also maintain
a set of added, updated and removed Model instances to be synchronized with the server via the Proxy. See the
Store docs for more information on Stores.
|
|
ModelConfig
|
|
|
ModelEvents
|
|
|
NodeInterface
|
This class is meant to be used as a set of methods that are applied to the prototype of a
Record to decorate it with a Node API. This means that models used in conjunction with a tree
will have all of the tree related methods available on the model. In general this class will
not be used directly by the developer.
|
|
NodeInterfaceConfig
|
|
|
NodeInterfaceEvents
|
|
|
Operation
|
Represents a single read or write operation performed by a Proxy.
Operation objects are used to enable communication between Stores and Proxies. Application
developers should rarely need to interact with Operation objects directly. Several Operations can be batched together in a batch.
|
|
OperationConfig
|
|
|
OperationEvents
|
|
|
Record
|
|
|
Request
|
Simple class that represents a Request that will be made by any Ext.data.proxy.Server subclass.
All this class does is standardize the representation of a Request as used by any ServerProxy subclass,
it does not contain any actual logic or perform the request itself.
|
|
RequestConfig
|
|
|
RequestEvents
|
|
|
ResultSet
|
Simple wrapper class that represents a set of records returned by a Proxy.
|
|
ResultSetConfig
|
|
|
ResultSetEvents
|
|
|
SortTypes
|
This class defines a series of static methods that are used on a
Ext.data.Field for performing sorting. The methods cast the
underlying values into a data type that is appropriate for sorting on
that particular field. If a Ext.data.Field.type is specified,
the sortType will be set to a sane default if the sortType is not
explicitly defined on the field. The sortType will make any necessary
modifications to the value and return it. asText - Removes any tags and converts the value to a string asUCText - Removes any tags and converts the value to an uppercase string asUCText - Converts the value to an uppercase string asDate - Converts the value into Unix epoch time asFloat - Converts the value to a floating point number asInt - Converts the value to an integer number
It is also possible to create a custom sortType that can be used throughout
an application.
Ext.apply(Ext.data.SortTypes, {
asPerson: function(person){
// expects an object with a first and last name property
return person.lastName.toUpperCase() + person.firstName.toLowerCase();
}
});
Ext.define('Employee', {
extend: 'Ext.data.Model',
fields: [{
name: 'person',
sortType: 'asPerson'
}, {
name: 'salary',
type: 'float' // sortType set to asFloat
}]
});
|
|
SortTypesConfig
|
|
|
SortTypesEvents
|
|
|
Store
|
The Store class encapsulates a client side cache of Model objects. Stores load
data via a Proxy, and also provide functions for sorting,
filtering and querying the model instances contained within it. Creating a Store is easy - we just tell it the Model and the Proxy to use to load and save its data: // Set up a model to use in our Store
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{name: 'firstName', type: 'string'},
{name: 'lastName', type: 'string'},
{name: 'age', type: 'int'},
{name: 'eyeColor', type: 'string'}
]
});
var myStore = new Ext.data.Store({
model: 'User',
proxy: {
type: 'ajax',
url : '/users.json',
reader: {
type: 'json',
root: 'users'
}
},
autoLoad: true
});
In the example above we configured an AJAX proxy to load data from the url '/users.json'. We told our Proxy
to use a JsonReader to parse the response from the server into Model object -
see the docs on JsonReader for details. Inline data Stores can also load data inline. Internally, Store converts each of the objects we pass in as data
into Model instances: new Ext.data.Store({
model: 'User',
data : [
{firstName: 'Ed', lastName: 'Spencer'},
{firstName: 'Tommy', lastName: 'Maintz'},
{firstName: 'Aaron', lastName: 'Conran'},
{firstName: 'Jamie', lastName: 'Avins'}
]
});
Loading inline data using the method above is great if the data is in the correct format already (e.g. it doesn't need
to be processed by a reader). If your inline data requires processing to decode the data structure,
use a MemoryProxy instead (see the MemoryProxy docs for an example). Additional data can also be loaded locally using add. Loading Nested Data Applications often need to load sets of associated data - for example a CRM system might load a User and her Orders.
Instead of issuing an AJAX request for the User and a series of additional AJAX requests for each Order, we can load a nested dataset
and allow the Reader to automatically populate the associated models. Below is a brief example, see the Ext.data.reader.Reader intro
docs for a full explanation: var store = new Ext.data.Store({
autoLoad: true,
model: "User",
proxy: {
type: 'ajax',
url : 'users.json',
reader: {
type: 'json',
root: 'users'
}
}
});
Which would consume a response like this: {
"users": [
{
"id": 1,
"name": "Ed",
"orders": [
{
"id": 10,
"total": 10.76,
"status": "invoiced"
},
{
"id": 11,
"total": 13.45,
"status": "shipped"
}
]
}
]
}
See the Ext.data.reader.Reader intro docs for a full explanation. Filtering and Sorting Stores can be sorted and filtered - in both cases either remotely or locally. The sorters and filters are
held inside MixedCollection instances to make them easy to manage. Usually it is sufficient to
either just specify sorters and filters in the Store configuration or call sort or filter:
var store = new Ext.data.Store({
model: 'User',
sorters: [
{
property : 'age',
direction: 'DESC'
},
{
property : 'firstName',
direction: 'ASC'
}
],
filters: [
{
property: 'firstName',
value : /Ed/
}
]
});
The new Store will keep the configured sorters and filters in the MixedCollection instances mentioned above. By default, sorting
and filtering are both performed locally by the Store - see remoteSort and remoteFilter to allow the server to
perform these operations instead. Filtering and sorting after the Store has been instantiated is also easy. Calling filter adds another filter to the Store
and automatically filters the dataset (calling filter with no arguments simply re-applies all existing filters). Note that by
default sortOnFilter is set to true, which means that your sorters are automatically reapplied if using local sorting. store.filter('eyeColor', 'Brown');
Change the sorting at any time by calling sort: store.sort('height', 'ASC');
Note that all existing sorters will be removed in favor of the new sorter data (if sort is called with no arguments,
the existing sorters are just reapplied instead of being removed). To keep existing sorters and add new ones, just add them
to the MixedCollection: store.sorters.add(new Ext.util.Sorter({
property : 'shoeSize',
direction: 'ASC'
}));
store.sort();
Registering with StoreManager Any Store that is instantiated with a storeId will automatically be registed with the StoreManager.
This makes it easy to reuse the same store in multiple views: //this store can be used several times
new Ext.data.Store({
model: 'User',
storeId: 'usersStore'
});
new Ext.List({
store: 'usersStore',
//other config goes here
});
new Ext.view.View({
store: 'usersStore',
//other config goes here
});
Further Reading Stores are backed up by an ecosystem of classes that enables their operation. To gain a full understanding of these
pieces and how they fit together, see: Proxy - overview of what Proxies are and how they are used Model - the core class in the data package Reader - used by any subclass of ServerProxy to read a response
|
|
StoreConfig
|
|
|
StoreEvents
|
|
|
StoreManager
|
Contains a collection of all stores that are created that have an identifier.
An identifier can be assigned by setting the storeId
property. When a store is in the StoreManager, it can be referred to via it's identifier:
Ext.create('Ext.data.Store', {
model: 'SomeModel',
storeId: 'myStore'
});
var store = Ext.data.StoreManager.lookup('myStore');
Also note that the lookup method is aliased to Ext.getStore for convenience.
If a store is registered with the StoreManager, you can also refer to the store by it's identifier when
registering it with any Component that consumes data from a store:
Ext.create('Ext.data.Store', {
model: 'SomeModel',
storeId: 'myStore'
});
Ext.create('Ext.view.View', {
store: 'myStore',
// other configuration here
});
TODO: Make this an AbstractMgr
|
|
StoreManagerConfig
|
|
|
StoreManagerEvents
|
|
|
Tree
|
This class is used as a container for a series of nodes. The nodes themselves maintain
the relationship between parent/child. The tree itself acts as a manager. It gives functionality
to retrieve a node by its identifier: getNodeById. The tree also relays events from any of it's child nodes, allowing them to be handled in a
centralized fashion. In general this class is not used directly, rather used internally
by other parts of the framework.
|
|
TreeConfig
|
|
|
TreeEvents
|
|
|
TreeStore
|
The TreeStore is a store implementation that is backed by by an Ext.data.Tree.
It provides convenience methods for loading nodes, as well as the ability to use
the hierarchical tree structure combined with a store. This class is generally used
in conjunction with Ext.tree.Panel. This class also relays many events from
the Tree for convenience. Using Models If no Model is specified, an implicit model will be created that implements Ext.data.NodeInterface.
The standard Tree fields will also be copied onto the Model for maintaining their state. Reading Nested Data For the tree to read nested data, the Ext.data.reader.Reader must be configured with a root property,
so the reader can find nested data for each node. If a root is not specified, it will default to
'children'.
|
|
TreeStoreConfig
|
|
|
TreeStoreEvents
|
|
|
Types
|
This is s static class containing the system-supplied data types which may be given to a Field. The properties in this class are used as type indicators in the Field class, so to
test whether a Field is of a certain type, compare the type property against properties
of this class. Developers may add their own application-specific data types to this class. Definition names must be UPPERCASE.
each type definition must contain three properties: convert : FunctionA function to convert raw data values from a data block into the data
to be stored in the Field. The function is passed the collowing parameters:
v : MixedThe data value as read by the Reader, if undefined will use
the configured defaultValue. rec : MixedThe data object containing the row as read by the Reader.
Depending on the Reader type, this could be an Array (ArrayReader), an object
(JsonReader), or an XML element. sortType : Function A function to convert the stored data into comparable form, as defined by Ext.data.SortTypes. type : String A textual data type name. For example, to create a VELatLong field (See the Microsoft Bing Mapping API) containing the latitude/longitude value of a datapoint on a map from a JsonReader data block
which contained the properties lat and long, you would define a new data type like this: // Add a new Field data type which stores a VELatLong object in the Record.
Ext.data.Types.VELATLONG = {
convert: function(v, data) {
return new VELatLong(data.lat, data.long);
},
sortType: function(v) {
return v.Latitude; // When sorting, order by latitude
},
type: 'VELatLong'
};
Then, when declaring a Model, use
var types = Ext.data.Types; // allow shorthand type access
Ext.define('Unit',
extend: 'Ext.data.Model',
fields: [
{ name: 'unitName', mapping: 'UnitName' },
{ name: 'curSpeed', mapping: 'CurSpeed', type: types.INT },
{ name: 'latitude', mapping: 'lat', type: types.FLOAT },
{ name: 'latitude', mapping: 'lat', type: types.FLOAT },
{ name: 'position', type: types.VELATLONG }
]
});
|
|
TypesConfig
|
|
|
TypesEvents
|
|
|
validations
|
This singleton contains a set of validation functions that can be used to validate any type
of data. They are most often used in Models, where they are automatically
set up and executed.
|
|
validationsConfig
|
|
|
validationsEvents
|
|
|