Ext JS 4 入门指南--The Data Package(数据包)

Data(数据)

The data package is what loads and saves all of the data in your application and consists of 41 classes, but there are three that are more important than all the others - Model, Store and Ext.data.proxy.Proxy. These are used by almost every application, and are supported by a number of satellite classes:

译:数据包是负责怎样加载和保存你应用程序中的所有数据,它由41个类组成。其中有三个类是最重要的,分别是模型(Model)、数据仓库(Store)和代理(Ext.data.proxy.Proxy)。它们几乎在每个应用程序中都被使用到,并且有很多相附类为它们提供支持。

Data package overview

Models and Stores (模型类和数据仓库)

The centerpiece of the data package is Ext.data.Model. A Model represents some type of data in an application - for example an e-commerce app might have models for Users, Products and Orders. At its simplest a Model is just a set of fields and their data. We’re going to look at four of the principal parts of Model — Fields, Proxies, Associations and Validations.

译:数据包的核心部件是模型(Ext.data.Model)。每个模型代表应用程序中的一些数据类型-例如一个电子商务应用程序应该有Users、Products、Orders等模型类。其最简单的模型仅设置一些字段和字段对应数据的集合。我们将重点研究模型类中的四个主要部分—字段(Fields)、代理(Proxies)、关联(Associations)和验证(Validations)。

Let's look at how we create a model now: 译:现在让我们看看如何创建一个模型:

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: [
        { name: 'id', type: 'int' },
        { name: 'name', type: 'string' }
    ]
});

Models are typically used with a Store, which is basically a collection of Model instances. Setting up a Store and loading its data is simple:

译:模型通常在数据仓库类(Store)中使用,这些数据仓库类主要是一些模型实例的集合。设置数据仓库类并且加载数据是非常简单的:

Ext.create('Ext.data.Store', {
    model: 'User',
    proxy: {
        type: 'ajax',
        url : 'users.json',
        reader: 'json'
    },
    autoLoad: true
});

We configured our Store to use an Ajax Proxy, telling it the url to load data from and the Reader used to decode the data. In this case our server is returning JSON, so we've set up a Json Reader to read the response. The store auto-loads a set of User model instances from the url users.json. The users.json url should return a JSON string that looks something like this:

译:我们配置我们的数据仓库类用Ajax代理(Ajax Proxy),告诉它加载数据的url地址和用来解码数据的读取器(Reader)。这样,我们的服务器将返回JSON格式的数据,我们可以使用设置的Json读取器(Json Reader)来解析响应的内容。上面创建的数据仓库类自动加载了从url地址users.json读取的User模型类实例集合。users.json返回如下所示的JSON字符串:

{
    success: true,
    users: [
        { id: 1, name: 'Ed' },
        { id: 2, name: 'Tommy' }
    ]
}

For a live demo please see the Simple Store example. 译:下面现场演示一个简单的数据仓库实例。

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: [
        {name: 'id', type: 'int'},
        {name: 'name', type: 'string'}
    ]
});

var userStore;
Ext.require('Ext.data.Store');
Ext.onReady(function() {
    userStore = Ext.create('Ext.data.Store', {
        model: 'User',
        autoLoad: true,

        proxy: {
            type: 'ajax',
            url: 'data/users.json',
            reader: {
                type: 'json',
                root: 'users',
                successProperty: 'success'
            }
        }
    });
});

Inline data(内联数据示例)

Stores can also load data inline. Internally, Store converts each of the objects we pass in as data into Model instances:
译:数据仓库也可以加载内联数据,数据仓库将每个传递进data中的对象转换为模型类实例:

Ext.create('Ext.data.Store', {
    model: 'User',
    data: [
        { firstName: 'Ed',    lastName: 'Spencer' },
        { firstName: 'Tommy', lastName: 'Maintz' },
        { firstName: 'Aaron', lastName: 'Conran' },
        { firstName: 'Jamie', lastName: 'Avins' }
    ]
});

Inline Data example 译:内联数据示例

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: ['firstName', 'lastName']
});

var userStore;
Ext.require('Ext.data.Store');
Ext.onReady(function() {
    userStore = Ext.create('Ext.data.Store', {
        model: 'User',
        data: [
            {firstName: 'Ed',    lastName: 'Spencer'},
            {firstName: 'Tommy', lastName: 'Maintz'},
            {firstName: 'Aaron', lastName: 'Conran'},
            {firstName: 'Jamie', lastName: 'Avins'}
        ]
    });
});

Sorting and Grouping(排序和分组)

Stores are able to perform sorting, filtering and grouping locally, as well as supporting remote sorting, filtering and grouping:
译:数据仓库类能执行本地排序,过滤分分组数据,也支持远程排序,过滤分分组数据:

Ext.create('Ext.data.Store', {
    model: 'User',

    sorters: ['name', 'id'],
    filters: {
        property: 'name',
        value   : 'Ed'
    },
    groupField: 'age',
    groupDir: 'DESC'
});

In the store we just created, the data will be sorted first by name then id; it will be filtered to only include Users with the name 'Ed' and the data will be grouped by age in descending order. It's easy to change the sorting, filtering and grouping at any time through the Store API. For a live demo, see the Sorting Grouping Filtering Store example.

译:我们刚刚创建的数据仓库类实例中,数据首先将按照name排序,其次按id排序;数据将被过滤为仅包含name为’Ed’的Users,并且数据将按年龄由大到小的顺序进行分组。在任何时间都可以通过调用数据仓库类的API,非常简单的更改数据的排序、过滤和分组方式。下面现场演示数据仓库的排序、分组、过滤实例。

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: [
        { name: 'id', type: 'int' },
        { name: 'name', type: 'string' },
        { name: 'age', type: 'int' },
        { name: 'bob', type: 'int' }

    ]
});

var userStore;
Ext.require('Ext.data.Store');
Ext.onReady(function() {
    userStore = Ext.create('Ext.data.Store', {
        model: 'User',
        autoLoad: true,

        sorters: ['name', 'id'], // sort first by name, then by id 译:首先按名字,然后按ID排序
        filters: {
            // filter the data to only include users with the name 'Ed' 译:过滤数据,仅包含姓名为:'Ed"的用户(users)
            property: 'name',
            value: 'Ed'
        },
        groupField: 'age',
        groupDir: 'DESC',

        proxy: {
            type: 'ajax',
            url: 'data/users.json',
            reader: {
                type: 'json',
                root: 'users',
                successProperty: 'success'
            }
        }
    });
});

Proxies (代理)

Proxies are used by Stores to handle the loading and saving of Model data. There are two types of Proxy: Client and Server. Examples of client proxies include Memory for storing data in the browser's memory and Local Storage which uses the HTML 5 local storage feature when available. Server proxies handle the marshaling of data to some remote server and examples include Ajax, JsonP and Rest.

译:数据仓库类使用代理处理模型数据的加载和保存。有两种代理类型:客户端代理(Client)和服务器端代理(Server)。客户端代理的例子包括 使用浏览器内存存储数据的内存方式和使用HTML5本地存储器(可用时)的本地存储方式。服务器代理处理一些从远程服务器返回的封装的数据,例如包括Ajax,JsonP和Rest。

Proxies can be defined directly on a Model like so: 译:代理可以直接在模型类中定义,如下:

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

// 使用用户模型的代理
Ext.create('Ext.data.Store', {
    model: 'User'
});

This helps us in two ways. First, it's likely that every Store that uses the User model will need to load its data the same way, so we avoid having to duplicate the Proxy definition for each Store. Second, we can now load and save Model data without a Store:

这对我们有两方面的好处:首先,使得每个使用User模型类的存储类实例以相同方式加载数据变得可行,这样我们避免了必须为每个存储类实例复制相同代理方式的定义。其次,现在我们可以不必使用存储类来加载和保存模型数据:

// Gives us a reference to the User class 创建一个User类的引用
var User = Ext.ModelMgr.getModel('User');

var ed = Ext.create('User', {
    name: 'Ed Spencer',
    age : 25
});

// We can save Ed directly without having to add him to a Store first because we 我们可以直接保存ed而不用先把它添加到一个存储类中,因为我们配置了 
// configured a RestProxy this will automatically send a POST request to the url /users 一个能自动发送一个POST请求到指定url的Rest代理 
ed.save({
    success: function(ed) {
        console.log("Saved Ed! His ID is "+ ed.getId());
    }
});

// Load User 1 and do something with it (performs a GET request to /users/1) 加载User 1并对其一些相关操作(执行一个GET请求到 /users/1) 
User.load(1, {
    success: function(user) {
        console.log("Loaded user 1: " + user.get('name'));
    }
});

There are also Proxies that take advantage of the new capabilities of HTML5 - LocalStorage and SessionStorage. Although older browsers don't support these new HTML5 APIs, they're so useful that a lot of applications will benefit enormously from their presence.

也有利用HTML5新功能-- LocalStorage和 SessionStorage – 的代理模式。尽管旧的浏览器不支持这些新的HTML5 APIs,它们仍然是有用的,因为很多应用程序将从这些新特性的存在中受益。

Example of a Model that uses a Proxy directly(直接在模型类中使用代理的例子)

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

var userStore;
Ext.require('Ext.data.Store');
Ext.onReady(function() {
    // Uses the User Model's Proxy
    userStore = Ext.create('Ext.data.Store', {
        model: 'User',
        autoLoad: true
    });

    // Gives us a reference to the User class
    var User = Ext.ModelMgr.getModel('User');

    var ed = Ext.create('User', {
        name: 'Ed Spencer',
        age : 25
    });

    // We can save Ed directly without having to add him to a Store first because we
    // configured a RestProxy this will automatically send a POST request to the url data/users
    ed.save({
        success: function(ed) {
            console.log("Saved Ed! His ID is "+ ed.getId());
        }
    });

    // Load User 1 and do something with it (performs a GET request to /users/1)
    User.load(1, {
        success: function(user) {
            console.log("Loaded user 1: " + user.get('name'));
        }
    });

});

Associations(关联)

Models can be linked together with the Associations API. Most applications deal with many different Models, and the Models are almost always related. A blog authoring application might have models for User, Post and Comment. Each User creates Posts and each Post receives Comments. We can express those relationships like so:

模型类之间可以通过关联API链接在一起。大多数应用程序需要处理很多不同的模型类,并且这些模型类之间通常是相关联的。例如一个博客写作应用程序可能有User(用户)、Post(文章)、Comment(评论)等模型类。每个用户(User)可以创建多篇文章(Posts),并且每篇文章接受很多评论(Comments)。我们可以如下表示这些关系:

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

    hasMany: 'Post' // shorthand for { model: 'Post', name: 'posts' }
});

Ext.define('Post', {
    extend: 'Ext.data.Model',
    fields: ['id', 'user_id', 'title', 'body'],

    proxy: {
        type: 'rest',
        url : 'data/posts',
        reader: {
            type: 'json',
            root: 'posts'
        }
    },
    belongsTo: 'User',
    hasMany: { model: 'Comment', name: 'comments' }
});

Ext.define('Comment', {
    extend: 'Ext.data.Model',
    fields: ['id', 'post_id', 'name', 'message'],

    belongsTo: 'Post'
});

It's easy to express rich relationships between different Models in your application. Each Model can have any number of associations with other Models and your Models can be defined in any order. Once we have a Model instance we can easily traverse the associated data - for example, if we wanted to log all Comments made on each Post for a given User, we can do something like this:

这将使得在你的应用程序中表示这种复杂关系变得简单。 每个模型类可以和其他模型类有任意多的关联,并且你的模型类可以按任意顺序定义。一旦我们创建了一个模型类实例,我们可以很轻松地遍历与其相关联的数据 -- 例如,如果我们想记录一个给定用户的每篇文章的所有相关评论,我们可以如下这样操作:

// Loads User with ID 1 and related posts and comments using User's Proxy
User.load(1, {
    success: function(user) {
        console.log("User: " + user.get('name'));

        user.posts().each(function(post) {
            console.log("Comments for post: " + post.get('title'));

            post.comments().each(function(comment) {
                console.log(comment.get('message'));
            });
        });
    }
});

Each of the hasMany associations we created above results in a new function being added to the Model. We declared that each User model hasMany Posts, which added the user.posts() function we used in the snippet above. Calling user.posts() returns a Store configured with the Post model. In turn, the Post model gets a comments() function because of the hasMany Comments association we set up.

上例我们创建每一个的hasMany关联将产生一个新方法添加到这个模型类上。我们声明的每个User模型类实例有许多(hasMany)文章(Posts),这将为我们添加user.posts()方法,如上面代码段中使用的那样。调用user.posts()方法将返回一个配置了Post模型的存储类实例。依次类推,Post模型实例获取了一个comments()方法,因为我们为其设置了hasMany 评论关联。

Associations aren't just helpful for loading data - they're useful for creating new records too:

关联不仅对加载数据来说是有用的,而且对创建新记录也是有用的:

user.posts().add({
    title: 'Ext JS 4.0 MVC Architecture',
    body: 'It\'s a great Idea to structure your Ext JS Applications using the built in MVC Architecture...'
});

user.posts().sync();

Here we instantiate a new Post, which is automatically given the User's id in the user_id field. Calling sync() saves the new Post via its configured Proxy - this, again, is an asynchronous operation to which you can pass a callback if you want to be notified when the operation completed.

这里我们实例化了一个新的Post模型类,该实例将自动把User中的id赋值给Post中的user_id字段。调用sync()方法,将通过配置的代理方式来保存新创建的Post模型类实例 – 再者,如果你想让操作完成时得到反馈,你可以调用异步操作并传递进一个回调函数来实现。

The belongsTo association also generates new methods on the model, here's how we can use those:

属于(belongsTo)关联也能在模型类实例中生成一个新方法,如我们下面介绍的这个示例:

// get the user reference from the post's belongsTo association
post.getUser(function(user) {
    console.log('Just got the user reference from the post: ' + user.get('name'))
});

// try to change the post's user
post.setUser(100, {
    callback: function(product, operation) {
        if (operation.wasSuccessful()) {
            console.log('Post\'s user was updated');
        } else {
            console.log('Post\'s user could not be updated');
        }
    }
});

Once more, the loading function (getUser) is asynchronous and requires a callback function to get at the user instance. The setUser method simply updates the foreign_key (user_id in this case) to 100 and saves the Post model. As usual, callbacks can be passed in that will be triggered when the save operation has completed - whether successful or not.

再次说明,加载函数(getUser)是异步调用的,并且需要一个回调函数作为参数来获得user实例。setUser方法仅更新外键(本例中的user_id字段)的值为100,并保存这个Post模型类实例。通常,不管成功与否,当保存操作完成时,传递进去的回调函数都将被触发。

Loading Nested Data(加载内嵌的数据)

You may be wondering why we passed a success function to the User.load call but didn't have to do so when accessing the User's posts and comments. This is because the above example assumes that when we make a request to get a user the server returns the user data in addition to all of its nested Posts and Comments. By setting up associations as we did above, the framework can automatically parse out nested data in a single request. Instead of making a request for the User data, another for the Posts data and then yet more requests to load the Comments for each Post, we can return all of the data in a single server response like this:

你或许想知道为什么调用User.load方法时,我们传递一个success方法,但当访问User的文章(Post)及评论(Comment)时我们并不需要这样做。这是因为上面的例子中,我们假定当发送请求以获取一个用户的信息时,服务器返回了该用户的数据及所有嵌套的文章和评论的数据。上例我们通过设置关联配置,框架在一次请求中就能自动解析出嵌套的数据。不是靠先发送一个请求获取用户数据,另一个请求获取文章数据,再发送其他请求以获取每篇文章的评论数据这种模式,我们可以在一次服务器响应中返回所有的数据,如下:

{
    success: true,
    users: [
        {
            id: 1,
            name: 'Ed',
            age: 25,
            gender: 'male',
            posts: [
                {
                    id   : 12,
                    title: 'All about data in Ext JS 4',
                    body : 'One areas that has seen the most improvement...',
                    comments: [
                        {
                            id: 123,
                            name: 'S Jobs',
                            message: 'One more thing'
                        }
                    ]
                }
            ]
        }
    ]
}

The data is all parsed out automatically by the framework. It's easy to configure your Models' Proxies to load data from almost anywhere, and their Readers to handle almost any response format. As with Ext JS 3, Models and Stores are used throughout the framework by many of the components such a Grids, Trees and Forms.

这些数据将被框架自动解析出来。配置模型类的代理方式以用来加载任何地方的数据会变得很轻松,并且它们的阅读器模式几乎可以处理任何格式的响应数据。和Ext JS 3一样,模型类和存储类在整个框架中被许多组件使用,例如表格,树,表单。

See the Associations and Validations demo for a working example of models that use relationships.(查看关联和验证(Associations and Validations)的演示示例以获取一个可实际操作并且具有关联关系的模型实例。)

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: ['id', 'name', 'age', 'gender'],
    validations: [
        {type: 'presence', name: 'name'},
        {type: 'length',   name: 'name', min: 5},
        {type: 'format',   name: 'age', matcher: /\d+/},
        {type: 'inclusion', name: 'gender', list: ['male', 'female']},
        {type: 'exclusion', name: 'name', list: ['admin']}
    ],

    proxy: {
        type: 'rest',
        url : 'data/users',
        reader: {
            type: 'json',
            root: 'users'
        }
    },

    hasMany: 'Post' // shorthand for {model: 'Post', name: 'posts'}
});

//define the Post model
Ext.define('Post', {
    extend: 'Ext.data.Model',
    fields: ['id', 'user_id', 'title', 'body'],

    proxy: {
        type: 'rest',
        url : 'data/posts',
        reader: {
            type: 'json',
            root: 'posts'
        }
    },
    belongsTo: 'User',
    hasMany: {model: 'Comment', name: 'comments'}
});

//define the Comment model
Ext.define('Comment', {
    extend: 'Ext.data.Model',
    fields: ['id', 'post_id', 'name', 'message'],

    belongsTo: 'Post'
});

Ext.require('Ext.data.Store');
Ext.onReady(function() {
    // Loads User with ID 1 and related posts and comments using User's Proxy
    User.load(1, {
        success: function(user) {
            console.log("User: " + user.get('name'));

            // loop through the user's posts and print out the comments
            user.posts().each(function(post) {
                console.log("Comments for post: " + post.get('title'));

                post.comments().each(function(comment) {
                    console.log(comment.get('message'));
                });

                // get the user reference from the post's belongsTo association
                post.getUser(function(user) {
                    console.log('Just got the user reference from the post: ' + user.get('name'))
                });

                // try to change the post's user
                post.setUser(100, {
                    callback: function(product, operation) {
                        if (operation.wasSuccessful()) {
                            console.log('Post\'s user was updated');
                        } else {
                            console.log('Post\'s user could not be updated');
                        }
                    }
                });

            });

            // create a new post
            user.posts().add({
                title: 'Ext JS 4.0 MVC Architecture',
                body: 'It\'s a great Idea to structure your Ext JS Applications using the built in MVC Architecture...'
            });

            // save the new post
            user.posts().sync();

        }
    });

    // now lets try to create a new user with as many validation errors as we can
    var newUser = Ext.create('User', {
        name: 'admin',
        age: 'twenty-nine',
        gender: 'not a valid gender'
    });

    // run some validation on the new user we just created
    var errors = newUser.validate();

    console.log('Is User valid?', errors.isValid()); //returns 'false' as there were validation errors
    console.log('All Errors:', errors.items); //returns the array of all errors found on this model instance

    console.log('Age Errors:', errors.getByField('age')); //returns the errors for the age field

});

Of course, it's possible to load your data in a non-nested fashion. This can be useful if you need to "lazy load" the relational data only when it's needed. Let's just load the User data like before, except we'll assume the response only includes the User data without any associated Posts. Then we'll add a call to user.posts().load() in our callback to get the related Post data:

当然,你可以以一种非嵌套的方式加载你的数据。如果你仅想需要时加载相关的数据,这种“懒惰加载”模式将可能是有效地。如前所做,我们仅加载User数据,除此之外,我们假定返回的响应仅包含User数据,没有任何相关联的文章(Post)数据。然后,我们在user.posts().load()方法添加回调函数中以获取相关的文章(Post)数据:

// Loads User with ID 1 User's Proxy
User.load(1, {
    success: function(user) {
        console.log("User: " + user.get('name'));

        // Loads posts for user 1 using Post's Proxy
        user.posts().load({
            callback: function(posts, operation) {
                Ext.each(posts, function(post) {
                    console.log("Comments for post: " + post.get('title'));

                    post.comments().each(function(comment) {
                        console.log(comment.get('message'));
                    });
                });
            }
        });
    }
});

For a full example see Lazy Associations(查看懒惰关联(Lazy Associations)模式可以获取一个完整的示例)

Validations(验证)

As of Ext JS 4 Models became a lot richer with support for validating their data. To demonstrate this we're going to build upon the example we used above for associations. First let's add some validations to the User model:

自Ext JS 4起,模型类由于提供了验证数据的功能而变得更加丰富精彩了。为了证明这点,我们将在前面使用过的关联例子的基础上构建一个示例。首先让我们添加一些验证到User模型类中:

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: ...,

    validations: [
        {type: 'presence', name: 'name'},
        {type: 'length',   name: 'name', min: 5},
        {type: 'format',   name: 'age', matcher: /\d+/},
        {type: 'inclusion', name: 'gender', list: ['male', 'female']},
        {type: 'exclusion', name: 'name', list: ['admin']}
    ],

    proxy: ...
});

Validations follow the same format as field definitions. In each case, we specify a field and a type of validation. The validations in our example are expecting the name field to be present and to be at least 5 characters in length, the age field to be a number, the gender field to be either "male" or "female", and the username to be anything but "admin". Some validations take additional optional configuration - for example the length validation can take min and max properties, format can take a matcher, etc. There are five validations built into Ext JS and adding custom rules is easy. First, let's meet the ones built right in:

验证和域定义遵循相同的代码格式。任何情况下,我们都可以指定一个域和一种验证类型。我们例子中的验证器配置要求name域必须存在,并且至少5个字符长,age域必须为数字,gender域的值只能为male或female,并且用户名可以为除了admin外的其他任何名称。一些验证器可能具有其他的可选配置 -- 例如,长度验证可以具有最大和最小属性,格式(format)可以具有匹配(matcher)属性等。Ext JS有五种内置的验证器,且可以轻松地添加用户自定义规则。首先让我们看看这五种类型:

  • presence simply ensures that the field has a value. Zero counts as a valid value but empty strings do not.
    存在(presence) 确保该域必须有确定值。0被看作有效值,但空字符串将不被视为有效值。
  • length ensures that a string is between a min and max length. Both constraints are optional.
    长度(length) 确保一个字符串长度位于最大和最小值之间。两个参数都是可选的。
  • format ensures that a string matches a regular expression format. In the example above we ensure that the age field is 4 numbers followed by at least one letter.
    格式(format) 确保一个字符串匹配指定的正则表达式。上例中我们确保age域必须为数字。
  • inclusion ensures that a value is within a specific set of values (e.g. ensuring gender is either male or female).
    包含(inclusion) 确保该域的值在指定的数值集合中(例如确保性别只能是男或女)。
  • exclusion ensures that a value is not one of the specific set of values (e.g. blacklisting usernames like 'admin').
    排除(exclusion) 确保该域的值不在指定的数值集合中(例如用户名不能为admin)

Now that we have a grasp of what the different validations do, let's try using them against a User instance. We'll create a user and run the validations against it, noting any failures:

既然我们已经理解了不同验证器的功能,让我们尝试在一个User实例中使用它们。我们创建一个user实例并在其中运行验证器,注意产生的任何错误:

// now lets try to create a new user with as many validation errors as we can
var newUser = Ext.create('User', {
    name: 'admin',
    age: 'twenty-nine',
    gender: 'not a valid gender'
});

// run some validation on the new user we just created
var errors = newUser.validate();

console.log('Is User valid?', errors.isValid()); //returns 'false' as there were validation errors
console.log('All Errors:', errors.items); //returns the array of all errors found on this model instance

console.log('Age Errors:', errors.getByField('age')); //returns the errors for the age field

The key function here is validate(), which runs all of the configured validations and returns an Errors object. This simple object is just a collection of any errors that were found, plus some convenience methods such as isValid() - which returns true if there were no errors on any field - and getByField(), which returns all errors for a given field.

这里的关键函数是validate(),该函数运行所有配置验证器并返回一个Errors对象。这个简单的对象为所有错误的集合,并且添加了一些便利的方法,例如isValid() -- 当任何域都没有错误产生时,返回true,还有getByField()方法,返回给定域产生的所有错误。

For a complete example that uses validations please see Associations and Validations(请查看关联和验证(Associations and Validations)示例以获取一个使用验证器的复杂例子。)

// define the User model
Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: ['id', 'name', 'age', 'gender'],
    validations: [
        {type: 'presence', name: 'name'},
        {type: 'length',   name: 'name', min: 5},
        {type: 'format',   name: 'age', matcher: /\d+/},
        {type: 'inclusion', name: 'gender', list: ['male', 'female']},
        {type: 'exclusion', name: 'name', list: ['admin']}
    ],

    proxy: {
        type: 'rest',
        url : 'data/users',
        reader: {
            type: 'json',
            root: 'users'
        }
    },

    hasMany: 'Post' // shorthand for {model: 'Post', name: 'posts'}
});

//define the Post model
Ext.define('Post', {
    extend: 'Ext.data.Model',
    fields: ['id', 'user_id', 'title', 'body'],

    proxy: {
        type: 'rest',
        url : 'data/posts',
        reader: {
            type: 'json',
            root: 'posts'
        }
    },
    belongsTo: 'User',
    hasMany: {model: 'Comment', name: 'comments'}
});

//define the Comment model
Ext.define('Comment', {
    extend: 'Ext.data.Model',
    fields: ['id', 'post_id', 'name', 'message'],

    belongsTo: 'Post'
});

Ext.require('Ext.data.Store');
Ext.onReady(function() {
    // Loads User with ID 1 and related posts and comments using User's Proxy
    User.load(1, {
        success: function(user) {
            console.log("User: " + user.get('name'));

            // loop through the user's posts and print out the comments
            user.posts().each(function(post) {
                console.log("Comments for post: " + post.get('title'));

                post.comments().each(function(comment) {
                    console.log(comment.get('message'));
                });

                // get the user reference from the post's belongsTo association
                post.getUser(function(user) {
                    console.log('Just got the user reference from the post: ' + user.get('name'))
                });

                // try to change the post's user
                post.setUser(100, {
                    callback: function(product, operation) {
                        if (operation.wasSuccessful()) {
                            console.log('Post\'s user was updated');
                        } else {
                            console.log('Post\'s user could not be updated');
                        }
                    }
                });

            });

            // create a new post
            user.posts().add({
                title: 'Ext JS 4.0 MVC Architecture',
                body: 'It\'s a great Idea to structure your Ext JS Applications using the built in MVC Architecture...'
            });

            // save the new post
            user.posts().sync();

        }
    });

    // now lets try to create a new user with as many validation errors as we can
    var newUser = Ext.create('User', {
        name: 'admin',
        age: 'twenty-nine',
        gender: 'not a valid gender'
    });

    // run some validation on the new user we just created(在我们刚刚创建的user实例中运行一些验证器)
    var errors = newUser.validate();

    console.log('Is User valid?', errors.isValid()); //returns 'false' as there were validation errors(当有验证器错误产生时,返回false)
    console.log('All Errors:', errors.items); //returns the array of all errors found on this model instance(返回该模型类实例所有错误组合成的数组)

    console.log('Age Errors:', errors.getByField('age')); //returns the errors for the age field(返回age域产生的错误)

});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值