feat: update table

pull/309/head
tangjinzhou 2018-12-11 20:59:23 +08:00
parent f38a45ff2c
commit 4bc2c5ccd2
3 changed files with 138 additions and 60 deletions

View File

@ -1,6 +1,7 @@
import VcTable from '../vc-table'
import classNames from 'classnames'
import shallowEqual from 'shallowequal'
import Pagination from '../pagination'
import Icon from '../icon'
import Spin from '../spin'
@ -308,8 +309,8 @@ export default {
}
},
getSorterFn () {
const { sSortOrder: sortOrder, sSortColumn: sortColumn } = this
getSorterFn (state) {
const { sSortOrder: sortOrder, sSortColumn: sortColumn } = state || this.$data
if (!sortOrder || !sortColumn ||
typeof sortColumn.sorter !== 'function') {
return
@ -323,25 +324,37 @@ export default {
return 0
}
},
isSameColumn (a, b) {
if (a && b && a.key && a.key === b.key) {
return true
}
return a === b || shallowEqual(a, b, (value, other) => {
if (typeof value === 'function' && typeof other === 'function') {
return value === other || value.toString() === other.toString()
}
})
},
toggleSortOrder (order, column) {
let { sSortOrder: sortOrder, sSortColumn: sortColumn } = this
if (!column.sorter) {
return
}
const { sSortOrder: sortOrder, sSortColumn: sortColumn } = this
//
const isSortColumn = this.isSortColumn(column)
if (!isSortColumn) { //
sortOrder = order
sortColumn = column
} else { //
if (sortOrder === order) { //
sortOrder = undefined
sortColumn = null
} else { //
sortOrder = order
}
let newSortOrder
// sortOrder
const oldSortOrder = this.isSameColumn(sortColumn, column) ? sortOrder : undefined
// //
if (!oldSortOrder) {
newSortOrder = 'descend'
} else if (oldSortOrder === 'descend') {
newSortOrder = 'ascend'
} else {
newSortOrder = undefined
}
const newState = {
sSortOrder: sortOrder,
sSortColumn: sortColumn,
sSortOrder: newSortOrder,
sSortColumn: newSortOrder ? column : null,
}
// Controlled
@ -423,7 +436,7 @@ export default {
const defaultSelection = this.store.getState().selectionDirty ? [] : this.getDefaultSelection()
let selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection)
const key = this.getRecordKey(record, rowIndex)
const pivot = this.$data.pivot
const { pivot } = this.$data
const rows = this.getFlatCurrentPageData()
let realIndex = rowIndex
if (this.$props.expandedRowRender) {
@ -635,7 +648,7 @@ export default {
},
getRecordKey (record, index) {
const rowKey = this.rowKey
const { rowKey } = this
const recordKey = (typeof rowKey === 'function')
? rowKey(record, index) : record[rowKey]
warning(recordKey !== undefined,
@ -724,11 +737,11 @@ export default {
renderColumnsDropdown (columns, locale) {
const { prefixCls, dropdownPrefixCls } = this
const { sSortOrder: sortOrder } = this
return treeMap(columns, (originColumn, i) => {
const column = { ...originColumn }
return treeMap(columns, (column, i) => {
const key = this.getColumnKey(column, i)
let filterDropdown
let sortButton
const isSortColumn = this.isSortColumn(column)
if ((column.filters && column.filters.length > 0) || column.filterDropdown) {
const colFilters = this.sFilters[key] || []
filterDropdown = (
@ -741,53 +754,81 @@ export default {
prefixCls={`${prefixCls}-filter`}
dropdownPrefixCls={dropdownPrefixCls || 'ant-dropdown'}
getPopupContainer={this.getPopupContainer}
key='filter-dropdown'
/>
)
}
if (column.sorter) {
const isSortColumn = this.isSortColumn(column)
if (isSortColumn) {
column.className = classNames(column.className, {
[`${prefixCls}-column-sort`]: sortOrder,
})
}
// const isSortColumn = this.isSortColumn(column)
// if (isSortColumn) {
// column.className = classNames(column.className, {
// [`${prefixCls}-column-sort`]: sortOrder,
// })
// }
const isAscend = isSortColumn && sortOrder === 'ascend'
const isDescend = isSortColumn && sortOrder === 'descend'
sortButton = (
<div class={`${prefixCls}-column-sorter`}>
<span
<div class={`${prefixCls}-column-sorter`} key='sorter'>
<Icon
class={`${prefixCls}-column-sorter-up ${isAscend ? 'on' : 'off'}`}
title='↑'
onClick={() => this.toggleSortOrder('ascend', column)}
>
<Icon type='caret-up' />
</span>
<span
type='caret-up'
theme='filled'
/>
<Icon
class={`${prefixCls}-column-sorter-down ${isDescend ? 'on' : 'off'}`}
title='↓'
onClick={() => this.toggleSortOrder('descend', column)}
>
<Icon type='caret-down' />
</span>
type='caret-down'
theme='filled'
/>
</div>
)
}
column.title = (
<span key={key}>
{column.title}
{sortButton}
{filterDropdown}
</span>
)
if (sortButton || filterDropdown) {
column.className = classNames(`${prefixCls}-column-has-filters`, column.className)
return {
...column,
className: classNames(column.className, {
[`${prefixCls}-column-has-actions`]: sortButton || filterDropdown,
[`${prefixCls}-column-has-filters`]: filterDropdown,
[`${prefixCls}-column-has-sorters`]: sortButton,
[`${prefixCls}-column-sort`]: isSortColumn && sortOrder,
}),
title: [
<div
key='title'
title={sortButton ? locale.sortTitle : undefined}
class={sortButton ? `${prefixCls}-column-sorters` : undefined}
onClick={() => this.toggleSortOrder(column)}
>
{this.renderColumnTitle(column.title)}
{sortButton}
</div>,
filterDropdown,
],
}
// column.title = (
// <span key={key}>
// {column.title}
// {sortButton}
// {filterDropdown}
// </span>
// )
return column
// if (sortButton || filterDropdown) {
// column.className = classNames(`${prefixCls}-column-has-filters`, column.className)
// }
// return column
})
},
renderColumnTitle (title) {
const { sFilters: filters, sSortOrder: sortOrder } = this.$data
// https://github.com/ant-design/ant-design/issues/11246#issuecomment-405009167
if (title instanceof Function) {
return title({
filters,
sortOrder,
})
}
return title
},
handleShowSizeChange (current, pageSize) {
const pagination = this.sPagination
pagination.onShowSizeChange(current, pageSize)
@ -854,7 +895,11 @@ export default {
sorter.field = state.sSortColumn.dataIndex
sorter.columnKey = this.getColumnKey(state.sSortColumn)
}
return [pagination, filters, sorter]
const extra = {
currentDataSource: this.getLocalData(state),
}
return [pagination, filters, sorter, extra]
},
findColumn (myKey) {
@ -909,12 +954,14 @@ export default {
} : item))
},
getLocalData () {
const { dataSource, sFilters: filters } = this
getLocalData (state) {
const currentState = state || this.$data
const { sFilters: filters } = currentState
const { dataSource } = this.$props
let data = dataSource || []
//
data = data.slice(0)
const sorterFn = this.getSorterFn()
const sorterFn = this.getSorterFn(currentState)
if (sorterFn) {
data = this.recursiveSort(data, sorterFn)
}

View File

@ -13,6 +13,13 @@ import { initDefaultProps, getOptionProps } from '../_util/props-util'
import { cloneElement } from '../_util/vnode'
import BaseMixin from '../_util/BaseMixin'
function stopPropagation (e) {
e.stopPropagation()
if (e.nativeEvent.stopImmediatePropagation) {
e.nativeEvent.stopImmediatePropagation()
}
}
export default {
mixins: [BaseMixin],
name: 'FilterMenu',
@ -76,6 +83,9 @@ export default {
// },
},
methods: {
getDropdownVisible () {
return this.neverShown ? false : this.sVisible
},
setNeverShown (column) {
const rootNode = this.$el
const filterBelongToScrollBody = !!closest(rootNode, `.ant-table-scroll`)
@ -111,6 +121,12 @@ export default {
handleConfirm () {
this.setVisible(false)
this.confirmFilter2()
// Call `setSelectedKeys` & `confirm` in the same time will make filter data not up to date
// https://github.com/ant-design/ant-design/issues/12284
this.$forceUpdate()
this.$nextTick(() => {
this.confirmFilter
})
},
onVisibleChange (visible) {
@ -188,14 +204,27 @@ export default {
if (typeof filterIcon === 'function') {
filterIcon = filterIcon(filterd)
}
const dropdownSelectedClass = filterd ? `${prefixCls}-selected` : ''
const dropdownIconClass = classNames({
[`${prefixCls}-selected`]: filterd,
[`${prefixCls}-open`]: this.getDropdownVisible(),
})
return filterIcon ? cloneElement(filterIcon, {
attrs: {
title: locale.filterTitle,
},
class: classNames(`${prefixCls}-icon`, filterIcon.className),
}) : <Icon title={locale.filterTitle} type='filter' class={dropdownSelectedClass} />
on: {
click: stopPropagation,
},
class: classNames(`${prefixCls}-icon`, dropdownIconClass, filterIcon.className),
})
: <Icon
title={locale.filterTitle}
type='filter'
theme='filled'
class={dropdownIconClass}
onClick={stopPropagation}
/>
},
},
@ -207,7 +236,7 @@ export default {
[`${dropdownPrefixCls}-menu-without-submenu`]: !this.hasSubMenu(),
})
let { filterDropdown } = column
if (filterDropdown && typeof filterDropdown === 'function') {
if (filterDropdown instanceof Function) {
filterDropdown = filterDropdown({
prefixCls: `${dropdownPrefixCls}-custom`,
setSelectedKeys: (selectedKeys) => this.setSelectedKeys({ selectedKeys }),
@ -257,7 +286,8 @@ export default {
return (
<Dropdown
trigger={['click']}
visible={this.neverShown ? false : this.sVisible}
placement='bottomRight'
visible={this.getDropdownVisible()}
onVisibleChange={this.onVisibleChange}
getPopupContainer={getPopupContainer}
forceRender

View File

@ -63,6 +63,7 @@ export const TableLocale = PropTypes.shape({
emptyText: PropTypes.any,
selectAll: PropTypes.any,
selectInvert: PropTypes.any,
sortTitle: PropTypes.string,
}).loose
export const RowSelectionType = PropTypes.oneOf(['checkbox', 'radio'])