Ext中文网

ajaxjs.com 面向 AJAX RIA 的专题网站 since 2006


 当前位置 » 首页 » 文档 Docs » guide » grid

Grids


Grid 面板不但是 Ext JS 的核心之一,而且还是一个通用性很强的组件。它提供了一个简单的方式来显示(display)、排序(sort)、分组(group)和编辑(edit)数据。

The Grid Panel is one of the centerpieces of Ext JS. It's an incredibly versatile component that provides an easy way to display, sort, group, and edit data.

基本Grid面板 Basic Grid Panel

Simple Grid

让我们开始创建一个基本的 Grid 面板。通过这个例子你可以学习到创建 Grid 的基本方法并让 Grid 顺利地跑起来。

Let's get started by creating a basic Grid Panel . Here's all you need to know to get a simple grid up and running:

模型对象 Model 和 Store 存储对象 Model and Store

一个 Grid 面板可以说仅仅是一个组件,它会把 Store 中的数据显示出来。Store 可以被看作是一记录集合,或模型的实例。欲了解更多 Store 和模型的信息,建议参阅该文。这种设计的好处是“各司其职(separation of concerns)”,并且十分清晰。Grid 面板只关注如何显示的数据,而 Store 则透过用其代理(Proxy)执行数据的获取和保存。

A Grid Panel is simply a component that displays data contained in a Store. A Store can be thought of as a collection of records, or Model instances. For more information on Stores and Models see the Data guide. The benefit of this setup is clear separation of concerns. The Grid Panel is only concerned with displaying the data, while the Store takes care of fetching and saving the data using its Proxy.

首先,我们需要定义一个模型。模型只是一种集合,表示一个数据类型的字段。让我们定义一个模型,它代表着“用户 User”:

First we need to define a Model. A Model is just a collection of fields that represents a type of data. Let's define a model that represents a "User":

Ext.define('User', {

extend
: 'Ext.data.Model',
fields
: [ 'name', 'email', 'phone' ]

});

接下来,我们创建一个包含多个用户 User 的 Store 对象。

Next let's create a Store that contains several User instances.

var userStore = Ext.create('Ext.data.Store', {

model
: 'User',
data
: [
{ name: 'Lisa', email: 'lisa@simpsons.com', phone: '555-111-1224' },

{ name: 'Bart', email: 'bart@simpsons.com', phone: '555-222-1234' },

{ name: 'Homer', email: 'home@simpsons.com', phone: '555-222-1244' },

{ name: 'Marge', email: 'marge@simpsons.com', phone: '555-222-1254' }

]
});

为了简单起见,我们直接写出 Store 其具体数据。而在真实的应用程序中,您通常会配置代理对象 Proxy,透过 Proxy 从服务器加载数据回来。更多请参阅使用 Proxy 的数据指导。

For sake of ease we configured the Store to load its data inline. In a real world application you'll usually configure the Store to use a Proxy to load data from the server. See the Data guide for more on using Proxies.

Grid Panel

当前我们有一 Model,Model 定义了我们的数据结构,然后将这几个 Model 实例添加到 Store,接着就可以使用 Grid 面板显示数据:

Now that we have a Model which defines our data structure, and we've loaded several Model instances into a Store, we're ready to display the data using a Grid Panel:

Ext.create('Ext.grid.Panel', {
renderTo
: Ext.getBody(),

store
: userStore,
width
: 400,
height
: 200,

title
: 'Application Users',
columns
: [
{
text
: 'Name',

width
: 100,
sortable
: false,
hideable
: false,

dataIndex
: 'name'
},
{
text
: 'Email Address',

width
: 150,
dataIndex
: 'email',
hidden
: true

},
{
text
: 'Phone Number',
flex
: 1,

dataIndex
: 'phone'
}
]
});

相当简单,是吧!我们刚刚创建的一个 Grid 面板,以 body 元素为容器,然后我们告诉它从我们前面创建的 userStore 中取出其数据。最后,我们不但定义了 Grid 面板将有哪些列,而且通过 dataIndex 属性来配置每列从用户领域模型中得到的数据。列“Name”指定其宽度为固定的 100px,把排序和隐藏列都禁用;列“email”默认是隐藏的(可通过其他列上面的菜单打开显示该列);列“Phone Number”配置了 flex 为 1,表示其宽度自适应 Grid 面板宽度,即除总宽度后剩下的宽度。要查看实例,请访问“简单的Grid示例”。

And that's all there is to it. We just created a Grid Panel that renders itself to the body element, and we told it to get its data from the userStore Store that we created earlier. Finally we defined what columns the Grid Panel will have, and we used the dataIndex property to configure which field in the User Model each column will get its data from. The Name column has a fixed width of 100px and has sorting and hiding disabled, the Email Address column is hidden by default (it can be shown again by using the menu on any other column), and the Phone Number column flexes to fit the remainder of the Grid Panel's total width. To view this example live, see the Simple Grid Example.

渲染器 Renderers

您可以通过列的 renderer 配置项来改变数据的现实方式。渲染器本身是一个函数,根据传入的原始值来进行修改,返回的那个值就是现实的值。最常见的一些渲染器都包含在 Ext.util.Format,当然你可以自定义渲染器:

You can use the renderer property of the column config to change the way data is displayed. A renderer is a function that modifies the underlying value and returns a new value to be displayed. Some of the most common renderers are included in Ext.util.Format, but you can write your own as well:

columns: [
{
text
: 'Birth Date',
dataIndex
: 'birthDate',

// format the date using a renderer from the Ext.util.Format class
renderer
: Ext.util.Format.dateRenderer('m/d/Y')

},
{
text
: 'Email Address',
dataIndex
: 'email',

// format the email address using a custom renderer
renderer
: function(value) {
return Ext.String.format('<a href="mailto:{0}">{1}</a>', value, value);

}
}
]

有关 Store、Proxy 用法,读者请参阅数据手册。

现场演示一下自定义渲染器渲染。

See the Renderers Example for a live demo that uses custom renderers.

分组 Grouping

Grouping Grid

把 Grid 里面的行进行分组很容易,首先要在 Store 身上指定 groupField 属性:

Organizing the rows in a Grid Panel into groups is easy, first we specify a groupField property on our store:

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

data
: ...,
groupField
: 'department'
});

更多 Store 的分组请参阅数据指导。接下来,我们将配置 Grid 的 Feature 配置项以便进行行分组:

For more on gouping in Stores please refer to the Data guide. Next we configure a grid with a grouping Feature that will handle displaying the rows in groups:

Ext.create('Ext.grid.Panel', {

...
features
: [{ ftype: 'grouping' }]
});

可参考一下 Grouping Grid Panel 在线例子。

See Grouping Grid Panel for a live example.

选区模型 Selection Models

有时 Grid 面板被用于只是在屏幕上显示的数据,但更多的是进行交互动作或执行更新数据的任务。所有 Grid 面板都有一个选择模型(Selection Model),以确定数据如何被选中。选择模型的两个主要类型是“整行选择模型”,抑或是“单元格选择模型”,也就是一行行地被选择,还是单个单元格被选中的问题。

Sometimes Grid Panels are use only to display data on the screen, but usually it is necessary to interact with or update that data. All Grid Panels have a Selection Model which determines how data is selected. The two main types of Selection Model are Row Selection Model, where entire rows are selected, and Cell Selection Model, where individual cells are selected.

Grid 面板默认使用行选择模型,但它很容易切换为单元格选择模型:

Grid Panels use a Row Selection Model by default, but it's easy to switch to a Cell Selection Model:

Ext.create('Ext.grid.Panel', {
selType
: 'cellmodel',
store
: ...

});

使用单元格选择模型的话,得改变几件事情。首先,点击一个单元格,选择的只是那个单元格(如使用行选择模型,将选择整个行);其次,键盘导航不是行与行之间的移动,而是单元格之间的。单元格为基础的选择模型通常与编辑控件一起使用。

Using a Cell Selection Model changes a couple of things. Firstly, clicking on a cell now selects just that cell (using a Row Selection Model will select the entire row), and secondly the keyboard navigation will walk from cell to cell instead of row to row. Cell-based selection models are usually used in conjunction with editing.

编辑 Editing

Grid 面板支持行编辑。我们要看看编辑的两个主要模式——行编辑和单元格编辑。

Grid Panel has build in support for editing. We're going to look at the two main editing modes - row editing and cell editing

单元格编辑 Cell Editing

单元格编辑就是允许你在 Grid 面板中针对某个单元格中的数据进行编辑。执行单元格编辑的第一步是配置每个 Grid面板 都应该是可编辑的列。以下就是编辑器的配置。最简单的方法是指定那个字段的 editor 为组件的 xtype:

Cell editing allows you to edit the data in a Grid Panel one cell at a time. The first step in implementing cell editing is to configure an editor for each Column in your Grid Panel that should be editable. This is done using the editor config. The simplest way is to specify just the xtype of the field you want to use as an editor:

Ext.create('Ext.grid.Panel', {
...
columns
: [

{
text
: 'Email Address',
dataIndex
: 'email',

editor
: 'textfield'
}
]
});

如果您需要更多的控制如何编辑字段的行为,编辑器配置也可以为字段的配置对象。例如,如果我们使用的是一个文本字段,我们需要一个值:

If you need more control over how the editor field behaves, the editor config can also take a config object for a Field. For example if we are using a Text Field and we want to require a value:

columns: [

text
: 'Name',
dataIndex
: 'name',
editor
: {

xtype
: 'textfield',
allowBlank
: false
}
]

作为一个编辑字段,您可以使用在Ext.form.field包的任何类。让我们假设我们要编辑一列包含日期。我们可以使用一个日期字段编辑器:

You can use any class in the Ext.form.field package as an editor field. Lets suppose we want to edit a column that contains dates. We can use a Date Field editor:

columns: [
{
text
: 'Birth Date',
dataIndex
: 'birthDate',

editor
: 'datefield'
}
]

不配置编辑器的任何一个Grid面板Ext.grid.column.Columns不会编辑。

Any Ext.grid.column.Columns in a Grid Panel that do not have a editor configured will not be editable. 

现在,我们已经配置了哪些可编辑的列,将使用的编辑器编辑数据字段,下一步是要指定一个选择模型。让我们用在我们的Grid面板配置的小区选择模型:

Now that we've configured which columns we want to be editable, and the editor fields that will be used to edit the data, the next step is to specify a selection model. Let's use a Cell Selection Model in our Grid Panel config:

Ext.create('Ext.grid.Panel', {

...
selType
: 'cellmodel'
});

最后打开编辑功能,我们为 Grid  面板配置上一个单元格编辑插件:

Finally, to enable editing we need to configure the Grid Panel with a Cell Editing Plugin:

Ext.create('Ext.grid.Panel', {

...
selType
: 'cellmodel',
plugins
: [
Ext.create('Ext.grid.plugin.CellEditing', {

clicksToEdit
: 1
})
]
});

而这一切都需要创建一个使用单元格编辑的 Grid,。请参阅单元格编辑实例。

And that's all it takes to create an editable grid using cell editing. See Cell Editing for a working example.

Cell Editing Grid

行编辑 Row Editing

行编辑,让您同时编辑编辑单元格,而不是整个行。行编辑的作品完全相同的单元格编辑相同的方式 - 所有我们需要做的的是改变插件类型Ext.grid.plugin.RowEditing和设置selType到rowmodel。

Row editing enables you to edit an entire row at a time, rather than editing cell by cell. Row editing works in exactly the same way as cell editing - all we need to do is change the plugin type to Ext.grid.plugin.RowEditing and set the selType to rowmodel.

Ext.create('Ext.grid.Panel', {

...
selType
: 'rowmodel',
plugins
: [
Ext.create('Ext.grid.plugin.RowEditing', {

clicksToEdit
: 1
})
]
});

行编辑的在线例子 Row Editing - Live Example

Row Editing Grid

分页 Paging

有时你的数据量太大,恰恰又要在一张页面上显示这些所有的数据,怎么办呢?Grid 面板支持两个不同方式的分页:1、使用“上一页/下一页”按钮的分页工具栏;2、使用滚动条进行上下翻页。

Sometimes your data set is too large to display all on one page. Grid Panel supports two different methods of paging - Paging Toolbar which loads pages using previous/next buttons, and Paging Scroller which loads new pages inline as you scroll.

设置 Store Store Setup

在设置Grid 两种类型的分页之前,我们必须要让 Store 支持分页。在下面的例子中,我们添加一个有 pageSize的Store,以及带有 totalProperty 配置项的 Reader:

Before we can set up either type of paging on a Grid Panel, we have to configure the Store to support paging. In the below example we add a pageSize to the Store, and we configure our Reader with a totalProperty:

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

autoLoad
: true,
pageSize
: 4,
proxy
: {

type
: 'ajax',
url
: 'data/users.json',
reader
: {

type
: 'json',
root
: 'users',
totalProperty
: 'total'

}
}
});

配置项 totalProperty 指定了从 JSON 结构中哪里可以获取结果的总数。该 Store 为 JsonStore 类型的,所以看起来像这样:

The totalProperty config tells the Reader where to get the total number of results in the JSON response. This Store is configured to consume a JSON response that looks something like this:

{
"success": true,
"total": 12,

"users": [
{ "name": "Lisa", "email": "lisa@simpsons.com", "phone": "555-111-1224" },

{ "name": "Bart", "email": "bart@simpsons.com", "phone": "555-222-1234" },

{ "name": "Homer", "email": "home@simpsons.com", "phone": "555-222-1244" },

{ "name": "Marge", "email": "marge@simpsons.com", "phone": "555-222-1254" }

]
}

For more on Stores, Proxies, and Readers refer to the Data Guide.

分页工具栏 Paging Toolbar

Now that we've setup our Store to support paging, all that's left is to configure a Paging Toolbar. You could put the Paging Toolbar anywhere in your application layout, but typically it is docked to the Grid Panel:

Ext.create('Ext.grid.Panel', {
store
: userStore,

columns
: ...,
dockedItems
: [{
xtype
: 'pagingtoolbar',

store
: userStore, // same store GridPanel is using
dock
: 'bottom',
displayInfo
: true

}]
});

Paging Toolbar

分页工具栏示例 Paging Toolbar Example

分页滚动 Paging Scroller

Grid 作为替代使用分页工具栏支持无限滚动。您的用户可以通过滚动数以千计的记录,却没有过多渲染记录而带来的性能损失。应指定Grid 其 Store 的 pageSize 的大小如何。

Grid supports infinite scrolling as an alternative to using a paging toolbar. Your users can scroll through thousands of records without the performance penalties of renderering all the records on screen at once. The grid should be bound to a store with a pageSize specified.

Ext.create('Ext.grid.Panel', {
// 使用PagingGridScroller (代替 PagingToolbar)Use a PagingGridScroller (this is interchangeable with a PagingToolbar)

verticalScrollerType
: 'paginggridscroller',
// 当刷新试图时不复位滚动条 do not reset the scrollbar when the view refreshs
invalidateScrollerOnRefresh
: false,

// 无限滚动不支持选择 infinite scrolling does not support selection
disableSelection
: true,
// ...
});

无限滚动示例 Infinite Scrolling Example