add table demo

pull/165/head
tangjinzhou 2018-04-03 14:34:54 +08:00
parent 100a7ca427
commit e37228e7a1
11 changed files with 607 additions and 14 deletions

View File

@ -70,14 +70,16 @@ export default {
getMenuElement () {
const { onClick, prefixCls, $slots } = this
this.childOriginEvents = getEvents($slots.overlay[0])
return cloneElement($slots.overlay[0], {
const extraOverlayProps = {
props: {
prefixCls: `${prefixCls}-menu`,
getPopupContainer: () => this.getPopupDomNode(),
},
on: {
click: onClick,
},
})
}
return cloneElement($slots.overlay[0], extraOverlayProps)
},
getPopupDomNode () {

View File

@ -133,12 +133,12 @@ export default {
const filteredValueColumns = this.getFilteredValueColumns(val)
if (filteredValueColumns.length > 0) {
const filtersFromColumns = this.getFiltersFromColumns(val)
const newFilters = { ...this.state.filters }
const newFilters = { ...this.sFilters }
Object.keys(filtersFromColumns).forEach(key => {
newFilters[key] = filtersFromColumns[key]
})
if (this.isFiltersChanged(newFilters)) {
this.setState({ filters: newFilters })
this.setState({ sFilters: newFilters })
}
}
},

View File

@ -11,15 +11,17 @@ Table with editable rows.
```html
<template>
<a-table :columns="columns" :dataSource="data" bordered>
<div v-for="col in ['name', 'age', 'address']" :key="col" :slot="col" slot-scope="text, record, index">
<a-input
v-if="record.editable"
style="margin: -5px 0"
:value="text"
@change="e => handleChange(e.target.value, record.key, col)"
/>
<template v-else>{{text}}</template>
</div>
<template v-for="col in ['name', 'age', 'address']" :slot="col" slot-scope="text, record, index">
<div>
<a-input
v-if="record.editable"
style="margin: -5px 0"
:value="text"
@change="e => handleChange(e.target.value, record.key, col)"
/>
<template v-else>{{text}}</template>
</div>
</template>
<template slot="operation" slot-scope="text, record, index">
<div class='editable-row-operations'>
<span v-if="record.editable">

View File

@ -0,0 +1,64 @@
<cn>
#### 固定列
对于列数很多的数据,可以固定前后的列,横向滚动查看其它数据,需要和 `scroll.x` 配合使用。
> 若列头与内容不对齐或出现列重复,请指定列的宽度 `width`
> 建议指定 `scroll.x` 为大于表格宽度的固定值或百分比。注意,且非固定列宽度之和不要超过 `scroll.x`
</cn>
<us>
#### Fixed Columns
To fix some columns and scroll inside other columns, and you must set `scoll.x` meanwhile.
> Specify the width of columns if header and cell do not align properly.
> A fixed value which is greater than table width for `scroll.x` is recommended. The sum of unfixed columns should not greater than `scroll.x`.
</us>
```html
<template>
<a-table :columns="columns" :dataSource="data" :scroll="{ x: 1300 }">
<a slot="action" slot-scope="text" href="#">action</a>
</a-table>
</template>
<script>
const columns = [
{ title: 'Full Name', width: 100, dataIndex: 'name', key: 'name', fixed: 'left' },
{ title: 'Age', width: 100, dataIndex: 'age', key: 'age', fixed: 'left' },
{ title: 'Column 1', dataIndex: 'address', key: '1' },
{ title: 'Column 2', dataIndex: 'address', key: '2' },
{ title: 'Column 3', dataIndex: 'address', key: '3' },
{ title: 'Column 4', dataIndex: 'address', key: '4' },
{ title: 'Column 5', dataIndex: 'address', key: '5' },
{ title: 'Column 6', dataIndex: 'address', key: '6' },
{ title: 'Column 7', dataIndex: 'address', key: '7' },
{ title: 'Column 8', dataIndex: 'address', key: '8' },
{
title: 'Action',
key: 'operation',
fixed: 'right',
width: 100,
scopedSlots: { customRender: 'action' },
},
];
const data = [{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York Park',
}, {
key: '2',
name: 'Jim Green',
age: 40,
address: 'London Park',
}];
export default {
data() {
return {
data,
columns,
}
}
}
</script>
```

View File

@ -0,0 +1,50 @@
<cn>
#### 固定表头
方便一页内展示大量数据。
需要指定 column 的 `width` 属性,否则列头和内容可能不对齐。
</cn>
<us>
#### Fixed Header
Display large amounts of data in scrollable view.
> Specify the width of each column if header and cell do not align properly.
</us>
```html
<template>
<a-table :columns="columns" :dataSource="data" :pagination="{ pageSize: 50 }" :scroll="{ y: 240 }" />
</template>
<script>
const columns = [{
title: 'Name',
dataIndex: 'name',
width: 150,
}, {
title: 'Age',
dataIndex: 'age',
width: 150,
}, {
title: 'Address',
dataIndex: 'address',
}];
const data = [];
for (let i = 0; i < 100; i++) {
data.push({
key: i,
name: `Edward King ${i}`,
age: 32,
address: `London, Park Lane no. ${i}`,
});
}
export default {
data() {
return {
data,
columns,
}
}
}
</script>
```

View File

@ -0,0 +1,109 @@
<cn>
#### 表头分组
`columns[n]` 可以内嵌 `children`,以渲染分组表头。
</cn>
<us>
#### Grouping table head
Group table head with `columns[n].children`.
</us>
```html
<template>
<a-table
:columns="columns"
:dataSource="data"
bordered
size="middle"
:scroll="{ x: '130%', y: 240 }"
/>
</template>
<script>
const columns = [{
title: 'Name',
dataIndex: 'name',
key: 'name',
width: 100,
fixed: 'left',
filters: [{
text: 'Joe',
value: 'Joe',
}, {
text: 'John',
value: 'John',
}],
onFilter: (value, record) => record.name.indexOf(value) === 0,
}, {
title: 'Other',
children: [{
title: 'Age',
dataIndex: 'age',
key: 'age',
width: 200,
sorter: (a, b) => a.age - b.age,
}, {
title: 'Address',
children: [{
title: 'Street',
dataIndex: 'street',
key: 'street',
width: 200,
}, {
title: 'Block',
children: [{
title: 'Building',
dataIndex: 'building',
key: 'building',
width: 100,
}, {
title: 'Door No.',
dataIndex: 'number',
key: 'number',
width: 100,
}],
}],
}],
}, {
title: 'Company',
children: [{
title: 'Company Address',
dataIndex: 'companyAddress',
key: 'companyAddress',
}, {
title: 'Company Name',
dataIndex: 'companyName',
key: 'companyName',
}],
}, {
title: 'Gender',
dataIndex: 'gender',
key: 'gender',
width: 60,
fixed: 'right',
}];
const data = [];
for (let i = 0; i < 100; i++) {
data.push({
key: i,
name: 'John Brown',
age: i + 1,
street: 'Lake Park',
building: 'C',
number: 2035,
companyAddress: 'Lake Street 42',
companyName: 'SoftLake Co',
gender: 'M',
});
}
export default {
data() {
return {
data,
columns,
}
}
}
</script>
```

View File

@ -0,0 +1,100 @@
<cn>
#### 筛选和排序
对某一列数据进行筛选,使用列的 `filters` 属性来指定需要筛选菜单的列,`onFilter` 用于筛选当前数据,`filterMultiple` 用于指定多选和单选。
对某一列数据进行排序,通过指定列的 `sorter` 函数即可启动排序按钮。`sorter: function(a, b) { ... }` a、b 为比较的两个列数据。
</cn>
<us>
#### Filter and sorter
Use `filters` to generate filter menu in columns, `onFilter` to determine filtered result, and `filterMultiple` to indicate whether it's multiple or single selection.
Use `sorter` to make a column sortable. `sorter` can be a function `function(a, b) { ... }` for sorting data locally.
</us>
```html
<template>
<a-table :columns="columns" :dataSource="data" @change="onChange"/>
</template>
<script>
const columns = [{
title: 'Name',
dataIndex: 'name',
filters: [{
text: 'Joe',
value: 'Joe',
}, {
text: 'Jim',
value: 'Jim',
}, {
text: 'Submenu',
value: 'Submenu',
children: [{
text: 'Green',
value: 'Green',
}, {
text: 'Black',
value: 'Black',
}],
}],
// specify the condition of filtering result
// here is that finding the name started with `value`
onFilter: (value, record) => record.name.indexOf(value) === 0,
sorter: (a, b) => a.name.length - b.name.length,
}, {
title: 'Age',
dataIndex: 'age',
sorter: (a, b) => a.age - b.age,
}, {
title: 'Address',
dataIndex: 'address',
filters: [{
text: 'London',
value: 'London',
}, {
text: 'New York',
value: 'New York',
}],
filterMultiple: false,
onFilter: (value, record) => record.address.indexOf(value) === 0,
sorter: (a, b) => a.address.length - b.address.length,
}];
const data = [{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
}, {
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
}, {
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
}, {
key: '4',
name: 'Jim Red',
age: 32,
address: 'London No. 2 Lake Park',
}];
function onChange(pagination, filters, sorter) {
console.log('params', pagination, filters, sorter);
}
export default {
data() {
return {
data,
columns,
}
},
methods: {
onChange,
}
}
</script>
```

View File

@ -0,0 +1,136 @@
<cn>
#### 嵌套子表格
展示每行数据更详细的信息。
</cn>
<us>
#### Nested tables
Showing more detailed info of every row.
</us>
```html
<template>
<a-table :columns="columns" :dataSource="data" class="components-table-demo-nested">
<a slot="operation" slot-scope="text" href="#">Publish</a>
<a-table
slot="expandedRowRender"
slot-scope="text"
:columns="innerColumns"
:dataSource="innerData"
:pagination="false"
>
<span slot="status" slot-scope="text">
<a-badge status="success" />Finished
</span>
<span slot="operation" slot-scope="text" class="table-operation">
<a href="#">Pause</a>
<a href="#">Stop</a>
<a-dropdown>
<a-menu slot="overlay">
<a-menu-item>
Action 1
</a-menu-item>
<a-menu-item>
Action 2
</a-menu-item>
</a-menu>
<a href="#">
More <a-icon type="down" />
</a>
</a-dropdown>
</span>
</a-table>
</a-table>
</template>
<script>
const columns = [
{ title: 'Name', dataIndex: 'name', key: 'name' },
{ title: 'Platform', dataIndex: 'platform', key: 'platform' },
{ title: 'Version', dataIndex: 'version', key: 'version' },
{ title: 'Upgraded', dataIndex: 'upgradeNum', key: 'upgradeNum' },
{ title: 'Creator', dataIndex: 'creator', key: 'creator' },
{ title: 'Date', dataIndex: 'createdAt', key: 'createdAt' },
{ title: 'Action', key: 'operation', scopedSlots: { customRender: 'operation' } },
];
const data = [];
for (let i = 0; i < 3; ++i) {
data.push({
key: i,
name: 'Screem',
platform: 'iOS',
version: '10.3.4.5654',
upgradeNum: 500,
creator: 'Jack',
createdAt: '2014-12-24 23:12:00',
});
}
const innerColumns = [
{ title: 'Date', dataIndex: 'date', key: 'date' },
{ title: 'Name', dataIndex: 'name', key: 'name' },
{ title: 'Status', key: 'state', scopedSlots: { customRender: 'status' } },
{ title: 'Upgrade Status', dataIndex: 'upgradeNum', key: 'upgradeNum' },
{
title: 'Action',
dataIndex: 'operation',
key: 'operation',
scopedSlots: { customRender: 'operation' },
},
];
const innerData = [];
for (let i = 0; i < 3; ++i) {
innerData.push({
key: i,
date: '2014-12-24 23:12:00',
name: 'This is production name',
upgradeNum: 'Upgraded: 56',
});
}
export default {
data() {
return {
data,
columns,
innerColumns,
innerData,
}
}
}
</script>
<style>
.components-table-demo-nested .ant-table-expanded-row > td:last-child {
padding: 0 48px 0 8px;
}
.components-table-demo-nested .ant-table-expanded-row > td:last-child .ant-table-thead th {
border-bottom: 1px solid #e9e9e9;
}
.components-table-demo-nested .ant-table-expanded-row > td:last-child .ant-table-thead th:first-child {
padding-left: 0;
}
.components-table-demo-nested .ant-table-expanded-row > td:last-child .ant-table-row td:first-child {
padding-left: 0;
}
.components-table-demo-nested .ant-table-expanded-row .ant-table-row:last-child td {
border: none;
}
.components-table-demo-nested .ant-table-expanded-row .ant-table-thead > tr > th {
background: none;
}
.components-table-demo-nested .table-operation a:not(:last-child) {
margin-right: 24px;
}
.components-table-demo-nested .ant-table-expanded-row:hover > td {
background: #fbfbfb;
}
</style>
```

View File

@ -0,0 +1,129 @@
<cn>
#### 可控的筛选和排序
使用受控属性对筛选和排序状态进行控制。
> 1. columns 中定义了 filteredValue 和 sortOrder 属性即视为受控模式。
> 2. 只支持同时对一列进行排序,请保证只有一列的 sortOrder 属性是生效的。
> 3. 务必指定 `column.key`
</cn>
<us>
#### Reset filters and sorters
Control filters and sorters by `filteredValue` and `sortOrder`.
> 1. Defining `filteredValue` or `sortOrder` means that it is in the controlled mode.
> 2. Make sure `sortOrder` is assigned for only one column.
> 3. `column.key` is required.
</us>
```html
<template>
<div>
<div class="table-operations">
<a-button @click="setAgeSort">Sort age</a-button>
<a-button @click="clearFilters">Clear filters</a-button>
<a-button @click="clearAll">Clear filters and sorters</a-button>
</div>
<a-table :columns="columns" :dataSource="data" @change="handleChange" />
</div>
</template>
<script>
const data = [{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
}, {
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
}, {
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
}, {
key: '4',
name: 'Jim Red',
age: 32,
address: 'London No. 2 Lake Park',
}];
export default {
data() {
return {
data,
filteredInfo: null,
sortedInfo: null,
}
},
computed: {
columns() {
let { sortedInfo, filteredInfo } = this;
sortedInfo = sortedInfo || {};
filteredInfo = filteredInfo || {};
const columns = [{
title: 'Name',
dataIndex: 'name',
key: 'name',
filters: [
{ text: 'Joe', value: 'Joe' },
{ text: 'Jim', value: 'Jim' },
],
filteredValue: filteredInfo.name || null,
onFilter: (value, record) => record.name.includes(value),
sorter: (a, b) => a.name.length - b.name.length,
sortOrder: sortedInfo.columnKey === 'name' && sortedInfo.order,
}, {
title: 'Age',
dataIndex: 'age',
key: 'age',
sorter: (a, b) => a.age - b.age,
sortOrder: sortedInfo.columnKey === 'age' && sortedInfo.order,
}, {
title: 'Address',
dataIndex: 'address',
key: 'address',
filters: [
{ text: 'London', value: 'London' },
{ text: 'New York', value: 'New York' },
],
filteredValue: filteredInfo.address || null,
onFilter: (value, record) => record.address.includes(value),
sorter: (a, b) => a.address.length - b.address.length,
sortOrder: sortedInfo.columnKey === 'address' && sortedInfo.order,
}];
return columns;
}
},
methods: {
handleChange (pagination, filters, sorter) {
console.log('Various parameters', pagination, filters, sorter);
this.filteredInfo = filters;
this.sortedInfo = sorter;
},
clearFilters () {
this.filteredInfo = null;
},
clearAll () {
this.filteredInfo = null;
this.sortedInfo = null;
},
setAgeSort () {
this.sortedInfo = {
order: 'descend',
columnKey: 'age',
}
}
}
}
</script>
<style scoped>
.table-operations {
margin-bottom: 16px;
}
.table-operations > button {
margin-right: 8px;
}
</style>
```

View File

@ -193,6 +193,7 @@ export default {
onSelect={this.setSelectedKeys}
onDeselect={this.setSelectedKeys}
selectedKeys={this.sSelectedKeys}
getPopupContainer={(triggerNode) => triggerNode.parentNode}
>
{this.renderMenus(column.filters)}
</Menu>

View File

@ -435,7 +435,7 @@ export default {
// const children = this.renderChildren(this.$slots.default)
const getPopupContainer = this.isRootMenu
? this.getPopupContainer : triggerNode => triggerNode.parentNode
? this.parentMenuContext.getPopupContainer : triggerNode => triggerNode.parentNode
const popupPlacement = popupPlacementMap[props.mode]
const popupClassName = props.mode === 'inline' ? '' : props.popupClassName
const liProps = {