add table demo
parent
a9e51adde6
commit
5a9b756338
|
@ -1,5 +1,4 @@
|
|||
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import VcTable from '../vc-table'
|
||||
import classNames from 'classnames'
|
||||
import Pagination from '../pagination'
|
||||
|
@ -33,10 +32,8 @@ function stopPropagation (e) {
|
|||
}
|
||||
|
||||
const defaultPagination = {
|
||||
on: {
|
||||
change: noop,
|
||||
showSizeChange: noop,
|
||||
},
|
||||
onChange: noop,
|
||||
onShowSizeChange: noop,
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,14 +88,13 @@ export default {
|
|||
watch: {
|
||||
pagination (val) {
|
||||
this.setState(previousState => {
|
||||
const newPagination = mergeProps(
|
||||
defaultPagination,
|
||||
previousState.sPagination,
|
||||
val,
|
||||
)
|
||||
newPagination.props = newPagination.props || {}
|
||||
newPagination.props.current = newPagination.props.current || 1
|
||||
newPagination.props.pageSize = newPagination.props.pageSize || 10
|
||||
const newPagination = {
|
||||
...defaultPagination,
|
||||
...previousState.sPagination,
|
||||
...val,
|
||||
}
|
||||
newPagination.current = newPagination.current || 1
|
||||
newPagination.pageSize = newPagination.pageSize || 10
|
||||
return { sPagination: val !== false ? newPagination : emptyObject }
|
||||
})
|
||||
},
|
||||
|
@ -176,17 +172,13 @@ export default {
|
|||
|
||||
getDefaultPagination (props) {
|
||||
const pagination = props.pagination || {}
|
||||
pagination.props = pagination.props || {}
|
||||
return this.hasPagination(props)
|
||||
? mergeProps(
|
||||
defaultPagination,
|
||||
pagination,
|
||||
{
|
||||
props: {
|
||||
current: pagination.props.defaultCurrent || pagination.props.current || 1,
|
||||
pageSize: pagination.props.defaultPageSize || pagination.props.pageSize || 10,
|
||||
},
|
||||
}) : {}
|
||||
? {
|
||||
...defaultPagination,
|
||||
...pagination,
|
||||
current: pagination.defaultCurrent || pagination.current || 1,
|
||||
pageSize: pagination.defaultPageSize || pagination.pageSize || 10,
|
||||
} : {}
|
||||
},
|
||||
|
||||
onRow (record, index) {
|
||||
|
@ -345,7 +337,7 @@ export default {
|
|||
if (this.getSortOrderColumns().length === 0) {
|
||||
this.setState(newState)
|
||||
}
|
||||
this.$emit('change', this.prepareParamsArguments({
|
||||
this.$emit('change', ...this.prepareParamsArguments({
|
||||
...this.$data,
|
||||
...newState,
|
||||
}))
|
||||
|
@ -373,9 +365,8 @@ export default {
|
|||
|
||||
if (props.pagination) {
|
||||
// Reset current prop
|
||||
pagination.props = pagination.props || {}
|
||||
pagination.props.current = 1
|
||||
pagination.on.change(pagination.current)
|
||||
pagination.current = 1
|
||||
pagination.onChange(pagination.current)
|
||||
}
|
||||
|
||||
const newState = {
|
||||
|
@ -395,23 +386,22 @@ export default {
|
|||
}
|
||||
|
||||
// Controlled current prop will not respond user interaction
|
||||
if (typeof props.pagination === 'object' && props.pagination.props && 'current' in (props.pagination.props)) {
|
||||
newState.sPagination = mergeProps(pagination, {
|
||||
props: {
|
||||
current: this.sPagination.props.current,
|
||||
},
|
||||
})
|
||||
if (typeof props.pagination === 'object' && 'current' in (props.pagination)) {
|
||||
newState.sPagination = {
|
||||
...pagination,
|
||||
current: this.sPagination.current,
|
||||
}
|
||||
}
|
||||
|
||||
this.setState(newState, () => {
|
||||
this.store.setState({
|
||||
selectionDirty: false,
|
||||
})
|
||||
this.$emit('change', this.prepareParamsArguments({
|
||||
this.$emit('change', ...this.prepareParamsArguments({
|
||||
...this.$data,
|
||||
selectionDirty: false,
|
||||
filters,
|
||||
pagination,
|
||||
sSelectionDirty: false,
|
||||
sFilters: filters,
|
||||
sPagination: pagination,
|
||||
}))
|
||||
})
|
||||
},
|
||||
|
@ -523,11 +513,11 @@ export default {
|
|||
const props = this.$props
|
||||
const pagination = { ...this.sPagination }
|
||||
if (current) {
|
||||
pagination.props.current = current
|
||||
pagination.current = current
|
||||
} else {
|
||||
pagination.props.current = pagination.props.current || 1
|
||||
pagination.current = pagination.current || 1
|
||||
}
|
||||
pagination.on.change(pagination.props.current, ...otherArguments)
|
||||
pagination.onChange(pagination.current, ...otherArguments)
|
||||
|
||||
const newState = {
|
||||
sPagination: pagination,
|
||||
|
@ -535,23 +525,21 @@ export default {
|
|||
// Controlled current prop will not respond user interaction
|
||||
if (props.pagination &&
|
||||
typeof props.pagination === 'object' &&
|
||||
props.pagination.props &&
|
||||
'current' in (props.pagination.props)) {
|
||||
newState.sPagination = mergeProps(pagination, {
|
||||
props: {
|
||||
current: this.sPagination.props.current,
|
||||
},
|
||||
})
|
||||
'current' in (props.pagination)) {
|
||||
newState.sPagination = {
|
||||
...pagination,
|
||||
current: this.sPagination.current,
|
||||
}
|
||||
}
|
||||
this.setState(newState)
|
||||
|
||||
this.store.setState({
|
||||
selectionDirty: false,
|
||||
})
|
||||
this.$emit('change', this.prepareParamsArguments({
|
||||
this.$emit('change', ...this.prepareParamsArguments({
|
||||
...this.$data,
|
||||
selectionDirty: false,
|
||||
pagination,
|
||||
sSelectionDirty: false,
|
||||
sPagination: pagination,
|
||||
}))
|
||||
},
|
||||
|
||||
|
@ -655,7 +643,7 @@ export default {
|
|||
},
|
||||
|
||||
getMaxCurrent (total) {
|
||||
const { current, pageSize } = this.sPagination.props
|
||||
const { current, pageSize } = this.sPagination
|
||||
if ((current - 1) * pageSize >= total) {
|
||||
return Math.floor((total - 1) / pageSize) + 1
|
||||
}
|
||||
|
@ -738,17 +726,16 @@ export default {
|
|||
|
||||
handleShowSizeChange (current, pageSize) {
|
||||
const pagination = this.sPagination
|
||||
pagination.on.showSizeChange(current, pageSize)
|
||||
const nextPagination = mergeProps(pagination, {
|
||||
props: {
|
||||
pageSize,
|
||||
current,
|
||||
},
|
||||
})
|
||||
pagination.onShowSizeChange(current, pageSize)
|
||||
const nextPagination = {
|
||||
...pagination,
|
||||
pageSize,
|
||||
current,
|
||||
}
|
||||
this.setState({ sPagination: nextPagination })
|
||||
this.$emit('change', this.prepareParamsArguments({
|
||||
this.$emit('change', ...this.prepareParamsArguments({
|
||||
...this.$data,
|
||||
pagination: nextPagination,
|
||||
sPagination: nextPagination,
|
||||
}))
|
||||
},
|
||||
|
||||
|
@ -759,25 +746,24 @@ export default {
|
|||
}
|
||||
let size = 'default'
|
||||
const { sPagination: pagination } = this
|
||||
if (pagination.props && pagination.props.size) {
|
||||
size = pagination.props.size
|
||||
if (pagination.size) {
|
||||
size = pagination.size
|
||||
} else if (this.size === 'middle' || this.size === 'small') {
|
||||
size = 'small'
|
||||
}
|
||||
const total = (pagination.props && pagination.props.total) || this.getLocalData().length
|
||||
const { class: cls, style, on, props } = pagination
|
||||
const total = pagination.total || this.getLocalData().length
|
||||
const { class: cls, style, onChange, onShowSizeChange, ...restProps } = pagination // eslint-disable-line
|
||||
const paginationProps = mergeProps({
|
||||
key: 'pagination',
|
||||
class: classNames(cls, `${this.prefixCls}-pagination`),
|
||||
props: {
|
||||
...props,
|
||||
...restProps,
|
||||
total,
|
||||
size,
|
||||
current: this.getMaxCurrent(total),
|
||||
},
|
||||
style,
|
||||
on: {
|
||||
...on,
|
||||
change: this.handlePageChange,
|
||||
showSizeChange: this.handleShowSizeChange,
|
||||
},
|
||||
|
@ -791,12 +777,10 @@ export default {
|
|||
|
||||
// Get pagination, filters, sorter
|
||||
prepareParamsArguments (state) {
|
||||
const pagination = cloneDeep(state.sPagination)
|
||||
const pagination = { ...state.sPagination }
|
||||
// remove useless handle function in Table.onChange
|
||||
if (pagination.on) {
|
||||
delete pagination.on.change
|
||||
delete pagination.on.showSizeChange
|
||||
}
|
||||
delete pagination.onChange
|
||||
delete pagination.onShowSizeChange
|
||||
const filters = state.sFilters
|
||||
const sorter = {}
|
||||
if (state.sSortColumn && state.sSortOrder) {
|
||||
|
@ -822,14 +806,14 @@ export default {
|
|||
let data = this.getLocalData()
|
||||
let current
|
||||
let pageSize
|
||||
const pagProps = this.sPagination.props || {}
|
||||
const sPagination = this.sPagination
|
||||
// 如果没有分页的话,默认全部展示
|
||||
if (!this.hasPagination()) {
|
||||
pageSize = Number.MAX_VALUE
|
||||
current = 1
|
||||
} else {
|
||||
pageSize = pagProps.pageSize
|
||||
current = this.getMaxCurrent(pagProps.total || data.length)
|
||||
pageSize = sPagination.pageSize
|
||||
current = this.getMaxCurrent(sPagination.total || data.length)
|
||||
}
|
||||
|
||||
// 分页
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
<cn>
|
||||
#### 远程加载数据
|
||||
这个例子通过简单的 ajax 读取方式,演示了如何从服务端读取并展现数据,具有筛选、排序等功能以及页面 loading 效果。开发者可以自行接入其他数据处理方式。
|
||||
另外,本例也展示了筛选排序功能如何交给服务端实现,列不需要指定具体的 `onFilter` 和 `sorter` 函数,而是在把筛选和排序的参数发到服务端来处理。
|
||||
**注意,此示例使用 [模拟接口](https://randomuser.me),展示数据可能不准确,请打开网络面板查看请求。**
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Ajax
|
||||
This example shows how to fetch and present data from remote server, and how to implement filtering and sorting in server side by sending related parameters to server.
|
||||
**Note, this example use [Mock API](https://randomuser.me) that you can look up in Network Console.**
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-table :columns="columns"
|
||||
:rowKey="record => record.registered"
|
||||
:dataSource="data"
|
||||
:pagination="pagination"
|
||||
:loading="loading"
|
||||
@change="handleTableChange"
|
||||
>
|
||||
<template slot="name" slot-scope="name">
|
||||
{{name.first}} {{name.last}}
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
<script>
|
||||
import reqwest from 'reqwest';
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
sorter: true,
|
||||
width: '20%',
|
||||
slotScopeName: 'name',
|
||||
}, {
|
||||
title: 'Gender',
|
||||
dataIndex: 'gender',
|
||||
filters: [
|
||||
{ text: 'Male', value: 'male' },
|
||||
{ text: 'Female', value: 'female' },
|
||||
],
|
||||
width: '20%',
|
||||
}, {
|
||||
title: 'Email',
|
||||
dataIndex: 'email',
|
||||
}];
|
||||
|
||||
export default {
|
||||
mounted() {
|
||||
this.fetch();
|
||||
},
|
||||
methods: {
|
||||
handleTableChange (pagination, filters, sorter) {
|
||||
console.log(pagination);
|
||||
const pager = { ...this.pagination };
|
||||
pager.current = pagination.current;
|
||||
this.pagination = pager;
|
||||
this.fetch({
|
||||
results: pagination.pageSize,
|
||||
page: pagination.current,
|
||||
sortField: sorter.field,
|
||||
sortOrder: sorter.order,
|
||||
...filters,
|
||||
});
|
||||
},
|
||||
fetch (params = {}) {
|
||||
console.log('params:', params);
|
||||
this.loading = true
|
||||
reqwest({
|
||||
url: 'https://randomuser.me/api',
|
||||
method: 'get',
|
||||
data: {
|
||||
results: 10,
|
||||
...params,
|
||||
},
|
||||
type: 'json',
|
||||
}).then((data) => {
|
||||
const pagination = { ...this.pagination };
|
||||
// Read total count from server
|
||||
// pagination.total = data.totalCount;
|
||||
pagination.total = 200;
|
||||
this.loading = false;
|
||||
this.data = data.results;
|
||||
this.pagination = pagination;
|
||||
});
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
data: [],
|
||||
pagination: {},
|
||||
loading: false,
|
||||
columns,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
|
@ -0,0 +1,76 @@
|
|||
<cn>
|
||||
#### 基本用法
|
||||
简单的表格,最后一列是各种操作。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### basic Usage
|
||||
Simple table with actions.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-table :columns="columns" :dataSource="data">
|
||||
<template slot="name" slot-scope="text">
|
||||
<a href="#">{{text}}</a>
|
||||
</template>
|
||||
<template slot="action" slot-scope="text, record">
|
||||
<span>
|
||||
<a href="#">Action 一 {{record.name}}</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#">Delete</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#" class="ant-dropdown-link">
|
||||
More actions <a-icon type="down" />
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
<script>
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
slotScopeName: 'name',
|
||||
}, {
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
}, {
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
}, {
|
||||
title: 'Action',
|
||||
key: 'action',
|
||||
slotScopeName: 'action',
|
||||
}];
|
||||
|
||||
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',
|
||||
}];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data,
|
||||
columns,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
|
@ -0,0 +1,76 @@
|
|||
<cn>
|
||||
#### 基本用法
|
||||
简单的表格,最后一列是各种操作。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### basic Usage
|
||||
Simple table with actions.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-table :columns="columns" :dataSource="data">
|
||||
<template slot="name" slot-scope="text">
|
||||
<a href="#">{{text}}</a>
|
||||
</template>
|
||||
<template slot="action" slot-scope="text, record">
|
||||
<span>
|
||||
<a href="#">Action 一 {{record.name}}</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#">Delete</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#" class="ant-dropdown-link">
|
||||
More actions <a-icon type="down" />
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
<script>
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
slotScopeName: 'name',
|
||||
}, {
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
}, {
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
}, {
|
||||
title: 'Action',
|
||||
key: 'action',
|
||||
slotScopeName: 'action',
|
||||
}];
|
||||
|
||||
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',
|
||||
}];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data,
|
||||
columns,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
|
@ -0,0 +1,76 @@
|
|||
<cn>
|
||||
#### 基本用法
|
||||
简单的表格,最后一列是各种操作。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### basic Usage
|
||||
Simple table with actions.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-table :columns="columns" :dataSource="data">
|
||||
<template slot="name" slot-scope="text">
|
||||
<a href="#">{{text}}</a>
|
||||
</template>
|
||||
<template slot="action" slot-scope="text, record">
|
||||
<span>
|
||||
<a href="#">Action 一 {{record.name}}</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#">Delete</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#" class="ant-dropdown-link">
|
||||
More actions <a-icon type="down" />
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
<script>
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
slotScopeName: 'name',
|
||||
}, {
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
}, {
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
}, {
|
||||
title: 'Action',
|
||||
key: 'action',
|
||||
slotScopeName: 'action',
|
||||
}];
|
||||
|
||||
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',
|
||||
}];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data,
|
||||
columns,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
|
@ -0,0 +1,76 @@
|
|||
<cn>
|
||||
#### 基本用法
|
||||
简单的表格,最后一列是各种操作。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### basic Usage
|
||||
Simple table with actions.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-table :columns="columns" :dataSource="data">
|
||||
<template slot="name" slot-scope="text">
|
||||
<a href="#">{{text}}</a>
|
||||
</template>
|
||||
<template slot="action" slot-scope="text, record">
|
||||
<span>
|
||||
<a href="#">Action 一 {{record.name}}</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#">Delete</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#" class="ant-dropdown-link">
|
||||
More actions <a-icon type="down" />
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
<script>
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
slotScopeName: 'name',
|
||||
}, {
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
}, {
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
}, {
|
||||
title: 'Action',
|
||||
key: 'action',
|
||||
slotScopeName: 'action',
|
||||
}];
|
||||
|
||||
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',
|
||||
}];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data,
|
||||
columns,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
|
@ -0,0 +1,76 @@
|
|||
<cn>
|
||||
#### 基本用法
|
||||
简单的表格,最后一列是各种操作。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### basic Usage
|
||||
Simple table with actions.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-table :columns="columns" :dataSource="data">
|
||||
<template slot="name" slot-scope="text">
|
||||
<a href="#">{{text}}</a>
|
||||
</template>
|
||||
<template slot="action" slot-scope="text, record">
|
||||
<span>
|
||||
<a href="#">Action 一 {{record.name}}</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#">Delete</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#" class="ant-dropdown-link">
|
||||
More actions <a-icon type="down" />
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
<script>
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
slotScopeName: 'name',
|
||||
}, {
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
}, {
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
}, {
|
||||
title: 'Action',
|
||||
key: 'action',
|
||||
slotScopeName: 'action',
|
||||
}];
|
||||
|
||||
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',
|
||||
}];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data,
|
||||
columns,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
|
@ -0,0 +1,76 @@
|
|||
<cn>
|
||||
#### 基本用法
|
||||
简单的表格,最后一列是各种操作。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### basic Usage
|
||||
Simple table with actions.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-table :columns="columns" :dataSource="data">
|
||||
<template slot="name" slot-scope="text">
|
||||
<a href="#">{{text}}</a>
|
||||
</template>
|
||||
<template slot="action" slot-scope="text, record">
|
||||
<span>
|
||||
<a href="#">Action 一 {{record.name}}</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#">Delete</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#" class="ant-dropdown-link">
|
||||
More actions <a-icon type="down" />
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
<script>
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
slotScopeName: 'name',
|
||||
}, {
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
}, {
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
}, {
|
||||
title: 'Action',
|
||||
key: 'action',
|
||||
slotScopeName: 'action',
|
||||
}];
|
||||
|
||||
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',
|
||||
}];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data,
|
||||
columns,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
|
@ -0,0 +1,71 @@
|
|||
<cn>
|
||||
#### 带边框
|
||||
添加表格边框线,页头和页脚。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### border, title and footer
|
||||
Add border, title and footer for table.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-table :columns="columns" :dataSource="data" bordered>
|
||||
<template slot="name" slot-scope="text">
|
||||
<a href="#">{{text}}</a>
|
||||
</template>
|
||||
<template slot="title" slot-scope="currentPageData">
|
||||
Header
|
||||
</template>
|
||||
<template slot="footer" slot-scope="currentPageData">
|
||||
Footer
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
<script>
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
slotScopeName: 'name',
|
||||
}, {
|
||||
title: 'Cash Assets',
|
||||
className: 'column-money',
|
||||
dataIndex: 'money',
|
||||
}, {
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
}];
|
||||
|
||||
const data = [{
|
||||
key: '1',
|
||||
name: 'John Brown',
|
||||
money: '¥300,000.00',
|
||||
address: 'New York No. 1 Lake Park',
|
||||
}, {
|
||||
key: '2',
|
||||
name: 'Jim Green',
|
||||
money: '¥1,256,000.00',
|
||||
address: 'London No. 1 Lake Park',
|
||||
}, {
|
||||
key: '3',
|
||||
name: 'Joe Black',
|
||||
money: '¥120,000.00',
|
||||
address: 'Sidney No. 1 Lake Park',
|
||||
}];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data,
|
||||
columns,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
th.column-money,
|
||||
td.column-money {
|
||||
text-align: right !important;
|
||||
}
|
||||
</style>
|
||||
```
|
|
@ -0,0 +1,143 @@
|
|||
<cn>
|
||||
#### 表格行/列合并
|
||||
表头只支持列合并,使用 column 里的 colSpan 进行设置。
|
||||
表格支持行/列合并,使用 render 里的单元格属性 colSpan 或者 rowSpan 设值为 0 时,设置的表格不会渲染。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### colSpan and rowSpan
|
||||
Table column title supports `colSpan` that set in `column`.
|
||||
Table cell supports `colSpan` and `rowSpan` that set in render return object. When each of them is set to `0`, the cell will not be rendered.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<a-table :columns="columns" :dataSource="data" bordered>
|
||||
<template slot="name" slot-scope="text">
|
||||
<a href="#">{{text}}</a>
|
||||
</template>
|
||||
<template slot="action" slot-scope="text, record">
|
||||
<span>
|
||||
<a href="#">Action 一 {{record.name}}</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#">Delete</a>
|
||||
<a-divider type="vertical" />
|
||||
<a href="#" class="ant-dropdown-link">
|
||||
More actions <a-icon type="down" />
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
<script>
|
||||
// In the fifth row, other columns are merged into first column
|
||||
// by setting it's colSpan to be 0
|
||||
const renderContent = (value, row, index) => {
|
||||
const obj = {
|
||||
children: value,
|
||||
props: {},
|
||||
};
|
||||
if (index === 4) {
|
||||
obj.props.colSpan = 0;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
|
||||
|
||||
const data = [{
|
||||
key: '1',
|
||||
name: 'John Brown',
|
||||
age: 32,
|
||||
tel: '0571-22098909',
|
||||
phone: 18889898989,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
}, {
|
||||
key: '2',
|
||||
name: 'Jim Green',
|
||||
tel: '0571-22098333',
|
||||
phone: 18889898888,
|
||||
age: 42,
|
||||
address: 'London No. 1 Lake Park',
|
||||
}, {
|
||||
key: '3',
|
||||
name: 'Joe Black',
|
||||
age: 32,
|
||||
tel: '0575-22098909',
|
||||
phone: 18900010002,
|
||||
address: 'Sidney No. 1 Lake Park',
|
||||
}, {
|
||||
key: '4',
|
||||
name: 'Jim Red',
|
||||
age: 18,
|
||||
tel: '0575-22098909',
|
||||
phone: 18900010002,
|
||||
address: 'London No. 2 Lake Park',
|
||||
}, {
|
||||
key: '5',
|
||||
name: 'Jake White',
|
||||
age: 18,
|
||||
tel: '0575-22098909',
|
||||
phone: 18900010002,
|
||||
address: 'Dublin No. 2 Lake Park',
|
||||
}];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
const columns = [{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
customRender: (text, row, index) => {
|
||||
if (index < 4) {
|
||||
return <a href="#">{text}</a>;
|
||||
}
|
||||
return {
|
||||
children: <a href="#">{text}</a>,
|
||||
props: {
|
||||
colSpan: 5,
|
||||
},
|
||||
};
|
||||
},
|
||||
}, {
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
render: renderContent,
|
||||
}, {
|
||||
title: 'Home phone',
|
||||
colSpan: 2,
|
||||
dataIndex: 'tel',
|
||||
customRender: (value, row, index) => {
|
||||
const obj = {
|
||||
children: value,
|
||||
props: {},
|
||||
};
|
||||
if (index === 2) {
|
||||
obj.props.rowSpan = 2;
|
||||
}
|
||||
// These two are merged into above cell
|
||||
if (index === 3) {
|
||||
obj.props.rowSpan = 0;
|
||||
}
|
||||
if (index === 4) {
|
||||
obj.props.colSpan = 0;
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
}, {
|
||||
title: 'Phone',
|
||||
colSpan: 0,
|
||||
dataIndex: 'phone',
|
||||
render: renderContent,
|
||||
}, {
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
render: renderContent,
|
||||
}];
|
||||
return {
|
||||
data,
|
||||
columns,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
|
@ -37,142 +37,139 @@ export default {
|
|||
this.setNeverShown(column)
|
||||
})
|
||||
},
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
const { column } = nextProps
|
||||
this.setNeverShown(column)
|
||||
const newState = {}
|
||||
if ('selectedKeys' in nextProps) {
|
||||
newState.selectedKeys = nextProps.selectedKeys
|
||||
}
|
||||
if ('filterDropdownVisible' in column) {
|
||||
newState.visible = column.filterDropdownVisible
|
||||
}
|
||||
if (Object.keys(newState).length > 0) {
|
||||
this.setState(newState)
|
||||
}
|
||||
watch: {
|
||||
'column.fixed': function (val) {
|
||||
this.setNeverShown(this.column)
|
||||
},
|
||||
column (val) {
|
||||
if ('filterDropdownVisible' in val) {
|
||||
this.sVisible = val.filterDropdownVisible
|
||||
}
|
||||
},
|
||||
selectedKeys (val) {
|
||||
this.sSelectedKeys = val
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
|
||||
setNeverShown (column) {
|
||||
const rootNode = this.$el
|
||||
const filterBelongToScrollBody = !!closest(rootNode, `.ant-table-scroll`)
|
||||
if (filterBelongToScrollBody) {
|
||||
// When fixed column have filters, there will be two dropdown menus
|
||||
// Filter dropdown menu inside scroll body should never be shown
|
||||
// To fix https://github.com/ant-design/ant-design/issues/5010 and
|
||||
// https://github.com/ant-design/ant-design/issues/7909
|
||||
this.neverShown = !!column.fixed
|
||||
}
|
||||
},
|
||||
|
||||
setSelectedKeys ({ selectedKeys }) {
|
||||
this.setState({ sSelectedKeys: selectedKeys })
|
||||
},
|
||||
|
||||
setVisible (visible) {
|
||||
const { column } = this
|
||||
if (!('filterDropdownVisible' in column)) {
|
||||
this.setState({ sVisible: visible })
|
||||
}
|
||||
if (column.onFilterDropdownVisibleChange) {
|
||||
column.onFilterDropdownVisibleChange(visible)
|
||||
}
|
||||
},
|
||||
|
||||
handleClearFilters () {
|
||||
this.setState({
|
||||
sSelectedKeys: [],
|
||||
}, this.handleConfirm)
|
||||
},
|
||||
|
||||
handleConfirm () {
|
||||
this.setVisible(false)
|
||||
this.confirmFilter()
|
||||
},
|
||||
|
||||
onVisibleChange (visible) {
|
||||
this.setVisible(visible)
|
||||
if (!visible) {
|
||||
this.confirmFilter()
|
||||
}
|
||||
},
|
||||
|
||||
confirmFilter () {
|
||||
if (this.sSelectedKeys !== this.selectedKeys) {
|
||||
this.confirmFilter(this.column, this.sSelectedKeys)
|
||||
}
|
||||
},
|
||||
|
||||
renderMenuItem (item) {
|
||||
const { column } = this
|
||||
const multiple = ('filterMultiple' in column) ? column.filterMultiple : true
|
||||
const input = multiple ? (
|
||||
<Checkbox checked={this.sSelectedKeys.indexOf(item.value.toString()) >= 0} />
|
||||
) : (
|
||||
<Radio checked={this.sSelectedKeys.indexOf(item.value.toString()) >= 0} />
|
||||
)
|
||||
|
||||
return (
|
||||
<MenuItem key={item.value}>
|
||||
{input}
|
||||
<span>{item.text}</span>
|
||||
</MenuItem>
|
||||
)
|
||||
},
|
||||
|
||||
hasSubMenu () {
|
||||
const { column: { filters = [] }} = this
|
||||
return filters.some(item => !!(item.children && item.children.length > 0))
|
||||
},
|
||||
|
||||
renderMenus (items) {
|
||||
return items.map(item => {
|
||||
if (item.children && item.children.length > 0) {
|
||||
const { sKeyPathOfSelectedItem } = this
|
||||
const containSelected = Object.keys(sKeyPathOfSelectedItem).some(
|
||||
key => sKeyPathOfSelectedItem[key].indexOf(item.value) >= 0,
|
||||
)
|
||||
const subMenuCls = containSelected ? `${this.dropdownPrefixCls}-submenu-contain-selected` : ''
|
||||
return (
|
||||
<SubMenu title={item.text} class={subMenuCls} key={item.value.toString()}>
|
||||
{this.renderMenus(item.children)}
|
||||
</SubMenu>
|
||||
)
|
||||
setNeverShown (column) {
|
||||
const rootNode = this.$el
|
||||
const filterBelongToScrollBody = !!closest(rootNode, `.ant-table-scroll`)
|
||||
if (filterBelongToScrollBody) {
|
||||
// When fixed column have filters, there will be two dropdown menus
|
||||
// Filter dropdown menu inside scroll body should never be shown
|
||||
// To fix https://github.com/ant-design/ant-design/issues/5010 and
|
||||
// https://github.com/ant-design/ant-design/issues/7909
|
||||
this.neverShown = !!column.fixed
|
||||
}
|
||||
return this.renderMenuItem(item)
|
||||
})
|
||||
},
|
||||
|
||||
setSelectedKeys ({ selectedKeys }) {
|
||||
this.setState({ sSelectedKeys: selectedKeys })
|
||||
},
|
||||
|
||||
setVisible (visible) {
|
||||
const { column } = this
|
||||
if (!('filterDropdownVisible' in column)) {
|
||||
this.setState({ sVisible: visible })
|
||||
}
|
||||
if (column.onFilterDropdownVisibleChange) {
|
||||
column.onFilterDropdownVisibleChange(visible)
|
||||
}
|
||||
},
|
||||
|
||||
handleClearFilters () {
|
||||
this.setState({
|
||||
sSelectedKeys: [],
|
||||
}, this.handleConfirm)
|
||||
},
|
||||
|
||||
handleConfirm () {
|
||||
this.setVisible(false)
|
||||
this.confirmFilter2()
|
||||
},
|
||||
|
||||
onVisibleChange (visible) {
|
||||
this.setVisible(visible)
|
||||
if (!visible) {
|
||||
this.confirmFilter2()
|
||||
}
|
||||
},
|
||||
|
||||
confirmFilter2 () {
|
||||
if (this.sSelectedKeys !== this.selectedKeys) {
|
||||
this.confirmFilter(this.column, this.sSelectedKeys)
|
||||
}
|
||||
},
|
||||
|
||||
renderMenuItem (item) {
|
||||
const { column } = this
|
||||
const multiple = ('filterMultiple' in column) ? column.filterMultiple : true
|
||||
const input = multiple ? (
|
||||
<Checkbox checked={this.sSelectedKeys.indexOf(item.value.toString()) >= 0} />
|
||||
) : (
|
||||
<Radio checked={this.sSelectedKeys.indexOf(item.value.toString()) >= 0} />
|
||||
)
|
||||
|
||||
return (
|
||||
<MenuItem key={item.value}>
|
||||
{input}
|
||||
<span>{item.text}</span>
|
||||
</MenuItem>
|
||||
)
|
||||
},
|
||||
|
||||
hasSubMenu () {
|
||||
const { column: { filters = [] }} = this
|
||||
return filters.some(item => !!(item.children && item.children.length > 0))
|
||||
},
|
||||
|
||||
renderMenus (items) {
|
||||
return items.map(item => {
|
||||
if (item.children && item.children.length > 0) {
|
||||
const { sKeyPathOfSelectedItem } = this
|
||||
const containSelected = Object.keys(sKeyPathOfSelectedItem).some(
|
||||
key => sKeyPathOfSelectedItem[key].indexOf(item.value) >= 0,
|
||||
)
|
||||
const subMenuCls = containSelected ? `${this.dropdownPrefixCls}-submenu-contain-selected` : ''
|
||||
return (
|
||||
<SubMenu title={item.text} class={subMenuCls} key={item.value.toString()}>
|
||||
{this.renderMenus(item.children)}
|
||||
</SubMenu>
|
||||
)
|
||||
}
|
||||
return this.renderMenuItem(item)
|
||||
})
|
||||
},
|
||||
|
||||
handleMenuItemClick (info) {
|
||||
if (info.keyPath.length <= 1) {
|
||||
return
|
||||
}
|
||||
const keyPathOfSelectedItem = this.sKeyPathOfSelectedItem
|
||||
if (this.sSelectedKeys.indexOf(info.key) >= 0) {
|
||||
// deselect SubMenu child
|
||||
delete keyPathOfSelectedItem[info.key]
|
||||
} else {
|
||||
// select SubMenu child
|
||||
keyPathOfSelectedItem[info.key] = info.keyPath
|
||||
}
|
||||
this.setState({ keyPathOfSelectedItem })
|
||||
},
|
||||
|
||||
renderFilterIcon () {
|
||||
const { column, locale, prefixCls } = this
|
||||
const filterIcon = column.filterIcon
|
||||
const dropdownSelectedClass = this.selectedKeys.length > 0 ? `${prefixCls}-selected` : ''
|
||||
|
||||
return filterIcon ? cloneElement(filterIcon, {
|
||||
title: locale.filterTitle,
|
||||
className: classNames(filterIcon.className, {
|
||||
[`${prefixCls}-icon`]: true,
|
||||
}),
|
||||
}) : <Icon title={locale.filterTitle} type='filter' class={dropdownSelectedClass} />
|
||||
},
|
||||
},
|
||||
|
||||
handleMenuItemClick (info) {
|
||||
if (info.keyPath.length <= 1) {
|
||||
return
|
||||
}
|
||||
const keyPathOfSelectedItem = this.sKeyPathOfSelectedItem
|
||||
if (this.sSelectedKeys.indexOf(info.key) >= 0) {
|
||||
// deselect SubMenu child
|
||||
delete keyPathOfSelectedItem[info.key]
|
||||
} else {
|
||||
// select SubMenu child
|
||||
keyPathOfSelectedItem[info.key] = info.keyPath
|
||||
}
|
||||
this.setState({ keyPathOfSelectedItem })
|
||||
},
|
||||
|
||||
renderFilterIcon () {
|
||||
const { column, locale, prefixCls } = this
|
||||
const filterIcon = column.filterIcon
|
||||
const dropdownSelectedClass = this.selectedKeys.length > 0 ? `${prefixCls}-selected` : ''
|
||||
|
||||
return filterIcon ? cloneElement(filterIcon, {
|
||||
title: locale.filterTitle,
|
||||
className: classNames(filterIcon.className, {
|
||||
[`${prefixCls}-icon`]: true,
|
||||
}),
|
||||
}) : <Icon title={locale.filterTitle} type='filter' class={dropdownSelectedClass} />
|
||||
},
|
||||
render () {
|
||||
const { column, locale, prefixCls, dropdownPrefixCls, getPopupContainer } = this
|
||||
// default multiple selection in filter dropdown
|
||||
|
|
|
@ -3,6 +3,7 @@ import T from './Table'
|
|||
import { getOptionProps, getKey, getClass,
|
||||
getStyle, getEvents, getSlotOptions, camelize, getSlots,
|
||||
} from '../_util/props-util'
|
||||
|
||||
const Table = {
|
||||
name: 'Table',
|
||||
Column: T.Column,
|
||||
|
@ -61,13 +62,19 @@ const Table = {
|
|||
},
|
||||
},
|
||||
render () {
|
||||
const { $listeners, $slots, normalize } = this
|
||||
const { $listeners, $slots, normalize, $scopedSlots } = this
|
||||
const props = getOptionProps(this)
|
||||
const columns = props.columns ? this.updateColumns(props.columns) : normalize($slots.default)
|
||||
let { title, footer } = props
|
||||
const { title: slotTitle, footer: slotFooter } = $scopedSlots
|
||||
title = title || slotTitle
|
||||
footer = footer || slotFooter
|
||||
const tProps = {
|
||||
props: {
|
||||
...props,
|
||||
columns,
|
||||
title,
|
||||
footer,
|
||||
},
|
||||
on: $listeners,
|
||||
}
|
||||
|
|
|
@ -108,8 +108,8 @@ export const TableProps = {
|
|||
useFixedHeader: PropTypes.bool,
|
||||
bordered: PropTypes.bool,
|
||||
showHeader: PropTypes.bool,
|
||||
footer: PropTypes.any,
|
||||
title: PropTypes.any,
|
||||
footer: PropTypes.func,
|
||||
title: PropTypes.func,
|
||||
scroll: PropTypes.object,
|
||||
childrenColumnName: PropTypes.string,
|
||||
bodyStyle: PropTypes.any,
|
||||
|
|
|
@ -14311,6 +14311,12 @@
|
|||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||
"dev": true
|
||||
},
|
||||
"reqwest": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/reqwest/-/reqwest-2.0.5.tgz",
|
||||
"integrity": "sha1-APsVrEkYxBnKgrQ/JMeIguZgOaE=",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
|
||||
|
|
|
@ -105,6 +105,7 @@
|
|||
"postcss-loader": "^2.1.2",
|
||||
"pre-commit": "^1.2.2",
|
||||
"querystring": "^0.2.0",
|
||||
"reqwest": "^2.0.5",
|
||||
"rimraf": "^2.6.2",
|
||||
"rucksack-css": "^1.0.2",
|
||||
"selenium-server": "^3.0.1",
|
||||
|
|
Loading…
Reference in New Issue