add table demo

pull/165/head
tjz 2018-04-01 22:33:01 +08:00
parent 5a9b756338
commit d7c2739c23
13 changed files with 364 additions and 180 deletions

View File

@ -4,7 +4,10 @@ import { Store } from './createStore'
const BodyRowProps = {
store: Store,
rowKey: PropTypes.string,
rowKey: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),
prefixCls: PropTypes.string,
}

View File

@ -0,0 +1,45 @@
<template>
<div class='editable-cell'>
<div v-if="editable" class='editable-cell-input-wrapper'>
<a-input
:value="value"
@change="handleChange"
@pressEnter="check"
/><a-icon
type='check'
class='editable-cell-icon-check'
@click="check"
/>
</div>
<div v-else class='editable-cell-text-wrapper'>
{{value || ' '}}
<a-icon type='edit' class='editable-cell-icon' @click="edit" />
</div>
</div>
</template>
<script>
export default {
props: {
text: String,
},
data () {
return {
value: this.text,
editable: false,
}
},
methods: {
handleChange (e) {
const value = e.target.value
this.value = value
},
check () {
this.editable = false
this.$emit('change', this.value)
},
edit () {
this.editable = true
},
},
}
</script>

View File

@ -50,6 +50,14 @@ export default {
mounted() {
this.fetch();
},
data() {
return {
data: [],
pagination: {},
loading: false,
columns,
}
},
methods: {
handleTableChange (pagination, filters, sorter) {
console.log(pagination);
@ -86,14 +94,6 @@ export default {
});
}
},
data() {
return {
data: [],
pagination: {},
loading: false,
columns,
}
}
}
</script>
```

View File

@ -1,76 +0,0 @@
<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>
```

View File

@ -1,76 +0,0 @@
<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>
```

View File

@ -35,10 +35,10 @@ Table cell supports `colSpan` and `rowSpan` that set in render return object. Wh
const renderContent = (value, row, index) => {
const obj = {
children: value,
props: {},
attrs: {},
};
if (index === 4) {
obj.props.colSpan = 0;
obj.attrs.colSpan = 0;
}
return obj;
};
@ -93,7 +93,7 @@ export default {
}
return {
children: <a href="#">{text}</a>,
props: {
attrs: {
colSpan: 5,
},
};
@ -101,7 +101,7 @@ export default {
}, {
title: 'Age',
dataIndex: 'age',
render: renderContent,
customRender: renderContent,
}, {
title: 'Home phone',
colSpan: 2,
@ -109,17 +109,17 @@ export default {
customRender: (value, row, index) => {
const obj = {
children: value,
props: {},
attrs: {},
};
if (index === 2) {
obj.props.rowSpan = 2;
obj.attrs.rowSpan = 2;
}
// These two are merged into above cell
if (index === 3) {
obj.props.rowSpan = 0;
obj.attrs.rowSpan = 0;
}
if (index === 4) {
obj.props.colSpan = 0;
obj.attrs.colSpan = 0;
}
return obj;
},
@ -127,11 +127,11 @@ export default {
title: 'Phone',
colSpan: 0,
dataIndex: 'phone',
render: renderContent,
customRender: renderContent,
}, {
title: 'Address',
dataIndex: 'address',
render: renderContent,
customRender: renderContent,
}];
return {
data,

View File

@ -0,0 +1,141 @@
<cn>
#### 自定义筛选菜单
通过 `filterDropdown`、`filterDropdownVisible` 和 `filterDropdownVisibleChange` 定义自定义的列筛选功能,并实现一个搜索列的示例。
</cn>
<us>
#### Customized filter panel
Implement a customized column search example via `filterDropdown`, `filterDropdownVisible` and `filterDropdownVisibleChange`.
</us>
```html
<template>
<a-table :dataSource="data">
<a-table-column
title="Name"
dataIndex="name"
key="name"
:filterDropdownVisible="filterDropdownVisible"
@filterDropdownVisibleChange="onFilterDropdownVisibleChange"
>
<div slot="filterDropdown" class="custom-filter-dropdown">
<a-input
ref="searchInput"
placeholder="Search name"
:value="searchText"
@change="onInputChange"
@pressEnter="onSearch"
/>
<a-button type="primary" @click="onSearch">Search</a-button>
</div>
<a-icon slot="filterIcon" type="smile-o" :style="{ color: this.filtered ? '#108ee9' : '#aaa' }" />
</a-table-column>
<a-table-column
title="Age"
dataIndex="age"
key="age"
/>
<a-table-column
title="Address"
dataIndex="address"
key="address"
:filters="filters"
@filter="(value, record) => record.address.indexOf(value) === 0"
/>
</a-table>
</template>
<script>
const data = [{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
}, {
key: '2',
name: 'Joe Black',
age: 42,
address: 'London No. 1 Lake Park',
}, {
key: '3',
name: 'Jim Green',
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 {
filterDropdownVisible: false,
data,
searchText: '',
filtered: false,
filters: [{
text: 'London',
value: 'London',
}, {
text: 'New York',
value: 'New York',
}],
}
},
methods: {
onFilterDropdownVisibleChange(visible) {
this.filterDropdownVisible = visible;
this.$nextTick(() => {
this.$refs.searchInput && this.$refs.searchInput.focus()
})
},
onInputChange(e) {
this.searchText = e.target.value;
},
onSearch () {
const { searchText } = this;
const reg = new RegExp(searchText, 'gi');
Object.assign(this, {
filterDropdownVisible: false,
filtered: !!searchText,
data: data.map((record) => {
const match = record.name.match(reg);
if (!match) {
return null;
}
return {
...record,
name: (
<span>
{record.name.split(reg).map((text, i) => (
i > 0 ? [<span class="highlight">{match[0]}</span>, text] : text
))}
</span>
),
};
}).filter(record => !!record),
})
},
},
}
</script>
<style scoped>
.custom-filter-dropdown {
padding: 8px;
border-radius: 6px;
background: #fff;
box-shadow: 0 1px 6px rgba(0, 0, 0, .2);
}
.custom-filter-dropdown input {
width: 130px;
margin-right: 8px;
}
.highlight {
color: #f50;
}
</style>
```

View File

@ -0,0 +1,145 @@
<cn>
#### 可编辑单元格
带单元格编辑功能的表格。
</cn>
<us>
#### Editable Cells
Table with editable cells.
</us>
```html
<template>
<div>
<a-button class="editable-add-btn" @click="handleAdd">Add</a-button>
<a-table bordered :dataSource="dataSource" :columns="columns">
<template slot="name" slot-scope="text, record">
<EditableCell :text="text" @change="onCellChange(record.key, 'name')"/>
</template>
<template slot="operation" slot-scope="text, record">
<a-popconfirm
v-if="dataSource.length"
title="Sure to delete?"
@confirm="() => onDelete(record.key)">
<a href="#">Delete</a>
</a-popconfirm>
</template>
</a-table>
</div>
</template>
<script>
import EditableCell from './EditableCell'
/*
* EditableCell Code https://github.com/vueComponent/ant-design/blob/master/components/table/demo/EditableCell.vue
*/
export default {
components: {
EditableCell,
},
data () {
return {
dataSource: [{
key: '0',
name: 'Edward King 0',
age: '32',
address: 'London, Park Lane no. 0',
}, {
key: '1',
name: 'Edward King 1',
age: '32',
address: 'London, Park Lane no. 1',
}],
count: 2,
columns: [{
title: 'name',
dataIndex: 'name',
width: '30%',
slotScopeName: 'name',
}, {
title: 'age',
dataIndex: 'age',
}, {
title: 'address',
dataIndex: 'address',
}, {
title: 'operation',
dataIndex: 'operation',
slotScopeName: 'operation',
}],
}
},
methods: {
onCellChange (key, dataIndex) {
return (value) => {
const dataSource = [...this.dataSource]
const target = dataSource.find(item => item.key === key)
if (target) {
target[dataIndex] = value
this.dataSource = dataSource
}
}
},
onDelete (key) {
const dataSource = [...this.dataSource]
this.dataSource = dataSource.filter(item => item.key !== key)
},
handleAdd () {
const { count, dataSource } = this
const newData = {
key: count,
name: `Edward King ${count}`,
age: 32,
address: `London, Park Lane no. ${count}`,
}
this.dataSource = [...dataSource, newData]
this.count = count + 1
},
},
}
</script>
<style>
.editable-cell {
position: relative;
}
.editable-cell-input-wrapper,
.editable-cell-text-wrapper {
padding-right: 24px;
}
.editable-cell-text-wrapper {
padding: 5px 24px 5px 5px;
}
.editable-cell-icon,
.editable-cell-icon-check {
position: absolute;
right: 0;
width: 20px;
cursor: pointer;
}
.editable-cell-icon {
line-height: 18px;
display: none;
}
.editable-cell-icon-check {
line-height: 28px;
}
.editable-cell:hover .editable-cell-icon {
display: inline-block;
}
.editable-cell-icon:hover,
.editable-cell-icon-check:hover {
color: #108ee9;
}
.editable-add-btn {
margin-bottom: 8px;
}
</style>
```

View File

@ -162,8 +162,10 @@ export default {
const dropdownSelectedClass = this.selectedKeys.length > 0 ? `${prefixCls}-selected` : ''
return filterIcon ? cloneElement(filterIcon, {
title: locale.filterTitle,
className: classNames(filterIcon.className, {
attrs: {
title: locale.filterTitle,
},
class: classNames(filterIcon.className, {
[`${prefixCls}-icon`]: true,
}),
}) : <Icon title={locale.filterTitle} type='filter' class={dropdownSelectedClass} />

View File

@ -23,11 +23,11 @@ const Table = {
const events = getEvents(element)
const listeners = {}
Object.keys(events).forEach(e => {
const k = `on_${e}`
const k = `on-${e}`
listeners[camelize(k)] = events[e]
})
const { default: children, title } = getSlots(element)
const column = { title, ...props, style, class: cls, ...listeners }
const { default: children, ...restSlots } = getSlots(element)
const column = { ...restSlots, ...props, style, class: cls, ...listeners }
if (key) {
column.key = key
}

View File

@ -173,7 +173,7 @@ export const SelectionBoxProps = {
export const FilterMenuProps = {
locale: TableLocale,
selectedKeys: PropTypes.arrayOf(PropTypes.string),
column: PropTypes.shape(ColumnProps),
column: PropTypes.object,
confirmFilter: PropTypes.func,
prefixCls: PropTypes.string,
dropdownPrefixCls: PropTypes.string,

View File

@ -23,7 +23,7 @@ const Table = {
const events = getEvents(element)
const listeners = {}
Object.keys(events).forEach(e => {
const k = `on_${e}`
const k = `on-${e}`
listeners[camelize(k)] = events[e]
})
const { default: children, title } = getSlots(element)

View File

@ -66,7 +66,8 @@ export default {
if (customRender) {
text = customRender(text, record, index)
if (this.isInvalidRenderCellText(text)) {
tdProps.attrs = text.attrs || text.props || {}
tdProps.attrs = text.attrs || {}
tdProps.props = text.props || {}
colSpan = tdProps.attrs.colSpan
rowSpan = tdProps.attrs.rowSpan
text = text.children
@ -93,7 +94,6 @@ export default {
if (rowSpan === 0 || colSpan === 0) {
return null
}
if (column.align) {
tdProps.style = { textAlign: column.align }
}