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域產生的錯誤)

});

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章