import PropTypes from '../../_util/vue-types' import BaseMixin from '../../_util/BaseMixin' import { connect } from '../../_util/store' import TableRow from './TableRow' import { remove } from './utils' import { initDefaultProps, getOptionProps } from '../../_util/props-util' export const ExpandableTableProps = () => ({ expandIconAsCell: PropTypes.bool, expandRowByClick: PropTypes.bool, expandedRowKeys: PropTypes.array, expandedRowClassName: PropTypes.func, defaultExpandAllRows: PropTypes.bool, defaultExpandedRowKeys: PropTypes.array, expandIconColumnIndex: PropTypes.number, expandedRowRender: PropTypes.func, childrenColumnName: PropTypes.string, indentSize: PropTypes.number, // onExpand: PropTypes.func, // onExpandedRowsChange: PropTypes.func, columnManager: PropTypes.object.isRequired, store: PropTypes.object.isRequired, prefixCls: PropTypes.string.isRequired, data: PropTypes.array, getRowKey: PropTypes.func, }) const ExpandableTable = { name: 'ExpandableTable', mixins: [BaseMixin], props: initDefaultProps(ExpandableTableProps(), { expandIconAsCell: false, expandedRowClassName: () => '', expandIconColumnIndex: 0, defaultExpandAllRows: false, defaultExpandedRowKeys: [], childrenColumnName: 'children', indentSize: 15, }), data () { const { data, childrenColumnName, defaultExpandAllRows, expandedRowKeys, defaultExpandedRowKeys, getRowKey, } = this let finnalExpandedRowKeys = [] let rows = [...data] if (defaultExpandAllRows) { for (let i = 0; i < rows.length; i++) { const row = rows[i] finnalExpandedRowKeys.push(getRowKey(row, i)) rows = rows.concat(row[childrenColumnName] || []) } } else { finnalExpandedRowKeys = expandedRowKeys || defaultExpandedRowKeys } // this.columnManager = props.columnManager // this.store = props.store this.store.setState({ expandedRowsHeight: {}, expandedRowKeys: finnalExpandedRowKeys, }) return {} }, watch: { expandedRowKeys (val) { this.$nextTick(() => { this.store.setState({ expandedRowKeys: val, }) }) }, }, methods: { handleExpandChange (expanded, record, event, rowKey, destroy = false) { if (event) { event.preventDefault() event.stopPropagation() } let { expandedRowKeys } = this.store.getState() if (expanded) { // row was expaned expandedRowKeys = [...expandedRowKeys, rowKey] } else { // row was collapse const expandedRowIndex = expandedRowKeys.indexOf(rowKey) if (expandedRowIndex !== -1) { expandedRowKeys = remove(expandedRowKeys, rowKey) } } if (!this.expandedRowKeys) { this.store.setState({ expandedRowKeys }) } this.__emit('expandedRowsChange', expandedRowKeys) if (!destroy) { this.__emit('expand', expanded, record) } }, renderExpandIndentCell (rows, fixed) { const { prefixCls, expandIconAsCell } = this if (!expandIconAsCell || fixed === 'right' || !rows.length) { return } const iconColumn = { key: 'rc-table-expand-icon-cell', className: `${prefixCls}-expand-icon-th`, title: '', rowSpan: rows.length, } rows[0].unshift({ ...iconColumn, column: iconColumn }) }, renderExpandedRow (record, index, expandedRowRender, className, ancestorKeys, indent, fixed) { const { prefixCls, expandIconAsCell, indentSize } = this const parentKey = ancestorKeys[ancestorKeys.length - 1] const rowKey = `${parentKey}-extra-row` const components = { body: { row: 'tr', cell: 'td', }, } let colCount if (fixed === 'left') { colCount = this.columnManager.leftLeafColumns().length } else if (fixed === 'right') { colCount = this.columnManager.rightLeafColumns().length } else { colCount = this.columnManager.leafColumns().length } const columns = [{ key: 'extra-row', customRender: () => { const { expandedRowKeys } = this.store.getState() const expanded = !!~expandedRowKeys.indexOf(parentKey) return { attrs: { colSpan: colCount, }, children: fixed !== 'right' ? expandedRowRender(record, index, indent, expanded) : ' ', } }, }] if (expandIconAsCell && fixed !== 'right') { columns.unshift({ key: 'expand-icon-placeholder', customRender: () => null, }) } return ( {}} /> ) }, renderRows (renderRows, rows, record, index, indent, fixed, parentKey, ancestorKeys) { const { expandedRowClassName, expandedRowRender, childrenColumnName } = this const childrenData = record[childrenColumnName] const nextAncestorKeys = [...ancestorKeys, parentKey] const nextIndent = indent + 1 if (expandedRowRender) { rows.push( this.renderExpandedRow( record, index, expandedRowRender, expandedRowClassName(record, index, indent), nextAncestorKeys, nextIndent, fixed, ), ) } if (childrenData) { rows.push(...renderRows(childrenData, nextIndent, nextAncestorKeys)) } }, }, render () { const { data, childrenColumnName, $scopedSlots, $listeners } = this const props = getOptionProps(this) const needIndentSpaced = data.some(record => record[childrenColumnName]) return $scopedSlots.default && $scopedSlots.default({ props, on: $listeners, needIndentSpaced, renderRows: this.renderRows, handleExpandChange: this.handleExpandChange, renderExpandIndentCell: this.renderExpandIndentCell, }) }, } export default connect()(ExpandableTable)