mirror of https://github.com/ElemeFE/element
Table: add expand row feature.
parent
c968525da9
commit
b569b314b8
|
@ -1354,6 +1354,94 @@ Customize table column so it can be integrated with other components.
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### Expandable row
|
||||||
|
|
||||||
|
When the row content is too long and you do not want to display the horizontal scroll bar, you can use the expandable row feature.
|
||||||
|
:::demo Activate expandable row by adding type="expand" and `inline-template` attribute,The template for `el-table-column` will be rendered as the contents of the expanded row, you can access the same attributes as the` inline-template`。
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<el-table
|
||||||
|
:data="tableData3"
|
||||||
|
style="width: 100%">
|
||||||
|
<el-table-column type="expand" inline-template>
|
||||||
|
<div>
|
||||||
|
<p>State: {{ row.state }}</p>
|
||||||
|
<p>City: {{ row.city }}</p>
|
||||||
|
<p>Address: {{ row.address }}</p>
|
||||||
|
<p>Zip: {{ row.zip }}</p>
|
||||||
|
</div>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="Date"
|
||||||
|
prop="date">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="Name"
|
||||||
|
prop="name">
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableData3: [{
|
||||||
|
date: '2016-05-03',
|
||||||
|
name: 'Tom',
|
||||||
|
state: 'California',
|
||||||
|
city: 'Los Angeles',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
zip: 'CA 90036'
|
||||||
|
}, {
|
||||||
|
date: '2016-05-02',
|
||||||
|
name: 'Tom',
|
||||||
|
state: 'California',
|
||||||
|
city: 'Los Angeles',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
zip: 'CA 90036'
|
||||||
|
}, {
|
||||||
|
date: '2016-05-04',
|
||||||
|
name: 'Tom',
|
||||||
|
state: 'California',
|
||||||
|
city: 'Los Angeles',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
zip: 'CA 90036'
|
||||||
|
}, {
|
||||||
|
date: '2016-05-01',
|
||||||
|
name: 'Tom',
|
||||||
|
state: 'California',
|
||||||
|
city: 'Los Angeles',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
zip: 'CA 90036'
|
||||||
|
}, {
|
||||||
|
date: '2016-05-08',
|
||||||
|
name: 'Tom',
|
||||||
|
state: 'California',
|
||||||
|
city: 'Los Angeles',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
zip: 'CA 90036'
|
||||||
|
}, {
|
||||||
|
date: '2016-05-06',
|
||||||
|
name: 'Tom',
|
||||||
|
state: 'California',
|
||||||
|
city: 'Los Angeles',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
zip: 'CA 90036'
|
||||||
|
}, {
|
||||||
|
date: '2016-05-07',
|
||||||
|
name: 'Tom',
|
||||||
|
state: 'California',
|
||||||
|
city: 'Los Angeles',
|
||||||
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
|
zip: 'CA 90036'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
### Table Attributes
|
### Table Attributes
|
||||||
| Attribute | Description | Type | Accepted Values | Default |
|
| Attribute | Description | Type | Accepted Values | Default |
|
||||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||||
|
@ -1369,7 +1457,9 @@ Customize table column so it can be integrated with other components.
|
||||||
| row-style | function that returns custom style for a row, or a string assigning custom style for every row | Function(row, index)/Object | — | — |
|
| row-style | function that returns custom style for a row, or a string assigning custom style for every row | Function(row, index)/Object | — | — |
|
||||||
| row-key | key of row data, used for optimizing rendering. Required if `reserve-selection` is on | Function(row)/String | — | — |
|
| row-key | key of row data, used for optimizing rendering. Required if `reserve-selection` is on | Function(row)/String | — | — |
|
||||||
| context | context of Table, e.g. `_self` refers to the current context, `$parent` parent context, `$root` root context, can be overridden by `context` in `el-table-column` | Object | - | current context where Table lies |
|
| context | context of Table, e.g. `_self` refers to the current context, `$parent` parent context, `$root` root context, can be overridden by `context` in `el-table-column` | Object | - | current context where Table lies |
|
||||||
| empty-text | Displayed text when data is empty. You can customize this area with `slot="empty"` | String | | - | No Data |
|
| empty-text | Displayed text when data is empty. You can customize this area with `slot="empty"` | String | - | No Data |
|
||||||
|
| default-expand-all | whether expand all rows by default, only works when the table has a column type="expand" | Boolean | - | false |
|
||||||
|
| expand-row-keys | set expanded rows by this prop, prop's value is the keys of expand rows, you should set row-key before using this prop | Array | - | |
|
||||||
|
|
||||||
### Table Events
|
### Table Events
|
||||||
| Event Name | Description | Parameters |
|
| Event Name | Description | Parameters |
|
||||||
|
@ -1387,6 +1477,7 @@ Customize table column so it can be integrated with other components.
|
||||||
| sort-change | triggers when Table's sorting changes | { column, prop, order } |
|
| sort-change | triggers when Table's sorting changes | { column, prop, order } |
|
||||||
| filter-change | column's key. If you need to use the filter-change event, this attribute is mandatory to identify which column is being filtered | filters |
|
| filter-change | column's key. If you need to use the filter-change event, this attribute is mandatory to identify which column is being filtered | filters |
|
||||||
| current-change | triggers when current row changes | currentRow, oldCurrentRow |
|
| current-change | triggers when current row changes | currentRow, oldCurrentRow |
|
||||||
|
| expand | triggers when user expands or collapses a row | row, expanded |
|
||||||
|
|
||||||
### Table Methods
|
### Table Methods
|
||||||
| Method | Description | Parameter |
|
| Method | Description | Parameter |
|
||||||
|
@ -1397,7 +1488,7 @@ Customize table column so it can be integrated with other components.
|
||||||
### Table-column Attributes
|
### Table-column Attributes
|
||||||
| Attribute | Description | Type | Accepted Values | Default |
|
| Attribute | Description | Type | Accepted Values | Default |
|
||||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||||
| type | type of the column. If set to `selection`, the column will display checkbox. If set to `index`, the column will display index of the row (staring from 1) | string | selection/index | — |
|
| type | type of the column. If set to `selection`, the column will display checkbox. If set to `index`, the column will display index of the row (staring from 1). If set to `expand`, the column will display expand icon. | string | selection/index/expand | — |
|
||||||
| label | column label | string | — | — |
|
| label | column label | string | — | — |
|
||||||
| column-key | column's key. If you need to use the filter-change event, you need this attribute to identify which column is being filtered | string | string | - | - |
|
| column-key | column's key. If you need to use the filter-change event, you need this attribute to identify which column is being filtered | string | string | - | - |
|
||||||
| prop | field name. You can also use its alias: `property` | string | — | — |
|
| prop | field name. You can also use its alias: `property` | string | — | — |
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
province: '上海',
|
province: '上海',
|
||||||
city: '普陀区',
|
city: '普陀区',
|
||||||
address: '上海市普陀区金沙江路 1518 弄',
|
address: '上海市普陀区金沙江路 1518 弄',
|
||||||
|
detailAddress: '金沙江路 1518 弄',
|
||||||
zip: 200333
|
zip: 200333
|
||||||
}, {
|
}, {
|
||||||
date: '2016-05-02',
|
date: '2016-05-02',
|
||||||
|
@ -67,6 +68,7 @@
|
||||||
province: '上海',
|
province: '上海',
|
||||||
city: '普陀区',
|
city: '普陀区',
|
||||||
address: '上海市普陀区金沙江路 1518 弄',
|
address: '上海市普陀区金沙江路 1518 弄',
|
||||||
|
detailAddress: '金沙江路 1518 弄',
|
||||||
zip: 200333
|
zip: 200333
|
||||||
}, {
|
}, {
|
||||||
date: '2016-05-04',
|
date: '2016-05-04',
|
||||||
|
@ -81,6 +83,7 @@
|
||||||
province: '上海',
|
province: '上海',
|
||||||
city: '普陀区',
|
city: '普陀区',
|
||||||
address: '上海市普陀区金沙江路 1518 弄',
|
address: '上海市普陀区金沙江路 1518 弄',
|
||||||
|
detailAddress: '金沙江路 1518 弄',
|
||||||
zip: 200333
|
zip: 200333
|
||||||
}, {
|
}, {
|
||||||
date: '2016-05-08',
|
date: '2016-05-08',
|
||||||
|
@ -88,6 +91,7 @@
|
||||||
province: '上海',
|
province: '上海',
|
||||||
city: '普陀区',
|
city: '普陀区',
|
||||||
address: '上海市普陀区金沙江路 1518 弄',
|
address: '上海市普陀区金沙江路 1518 弄',
|
||||||
|
detailAddress: '金沙江路 1518 弄',
|
||||||
zip: 200333
|
zip: 200333
|
||||||
}, {
|
}, {
|
||||||
date: '2016-05-06',
|
date: '2016-05-06',
|
||||||
|
@ -95,6 +99,7 @@
|
||||||
province: '上海',
|
province: '上海',
|
||||||
city: '普陀区',
|
city: '普陀区',
|
||||||
address: '上海市普陀区金沙江路 1518 弄',
|
address: '上海市普陀区金沙江路 1518 弄',
|
||||||
|
detailAddress: '金沙江路 1518 弄',
|
||||||
zip: 200333
|
zip: 200333
|
||||||
}, {
|
}, {
|
||||||
date: '2016-05-07',
|
date: '2016-05-07',
|
||||||
|
@ -102,6 +107,7 @@
|
||||||
province: '上海',
|
province: '上海',
|
||||||
city: '普陀区',
|
city: '普陀区',
|
||||||
address: '上海市普陀区金沙江路 1518 弄',
|
address: '上海市普陀区金沙江路 1518 弄',
|
||||||
|
detailAddress: '金沙江路 1518 弄',
|
||||||
zip: 200333
|
zip: 200333
|
||||||
}],
|
}],
|
||||||
tableData4: [{
|
tableData4: [{
|
||||||
|
@ -1363,6 +1369,74 @@
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### 展开行
|
||||||
|
|
||||||
|
当行内容过多并且不想显示横向滚动条时,可以使用 Table 展开行功能。
|
||||||
|
:::demo 通过设置 type="expand" 和 `inline-template` 属性可以开启展开行功能,`el-table-column` 的模板会被渲染成为展开行的内容,展开行可访问的属性与使用 `inline-template` 的时候相同。
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<el-table
|
||||||
|
:data="tableData3"
|
||||||
|
style="width: 100%">
|
||||||
|
<el-table-column type="expand" inline-template>
|
||||||
|
<div>
|
||||||
|
<p>省: {{ row.province }}</p>
|
||||||
|
<p>市: {{ row.city }}</p>
|
||||||
|
<p>住址: {{ row.detailAddress }}</p>
|
||||||
|
<p>邮编: {{ row.zip }}</p>
|
||||||
|
</div>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="日期"
|
||||||
|
prop="date">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
label="姓名"
|
||||||
|
prop="name">
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableData3: [{
|
||||||
|
date: '2016-05-02',
|
||||||
|
name: '王小虎',
|
||||||
|
province: '上海',
|
||||||
|
city: '普陀区',
|
||||||
|
detailAddress: '金沙江路 1518 弄',
|
||||||
|
zip: 200333
|
||||||
|
}, {
|
||||||
|
date: '2016-05-04',
|
||||||
|
name: '王小虎',
|
||||||
|
province: '上海',
|
||||||
|
city: '普陀区',
|
||||||
|
detailAddress: '金沙江路 1518 弄',
|
||||||
|
zip: 200333
|
||||||
|
}, {
|
||||||
|
date: '2016-05-01',
|
||||||
|
name: '王小虎',
|
||||||
|
province: '上海',
|
||||||
|
city: '普陀区',
|
||||||
|
detailAddress: '金沙江路 1518 弄',
|
||||||
|
zip: 200333
|
||||||
|
}, {
|
||||||
|
date: '2016-05-03',
|
||||||
|
name: '王小虎',
|
||||||
|
province: '上海',
|
||||||
|
city: '普陀区',
|
||||||
|
detailAddress: '金沙江路 1518 弄',
|
||||||
|
zip: 200333
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
### Table Attributes
|
### Table Attributes
|
||||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||||
|
@ -1377,7 +1451,9 @@
|
||||||
| row-style | 行的 style 的回调方法,也可以使用一个固定的 Object 为所有行设置一样的 Style。 | Function(row, index)/Object | — | — |
|
| row-style | 行的 style 的回调方法,也可以使用一个固定的 Object 为所有行设置一样的 Style。 | Function(row, index)/Object | — | — |
|
||||||
| row-key | 行数据的 Key,用来优化 Table 的渲染;在使用 reserve-selection 功能的情况下,该属性是必填的 | Function(row)/String | — | — |
|
| row-key | 行数据的 Key,用来优化 Table 的渲染;在使用 reserve-selection 功能的情况下,该属性是必填的 | Function(row)/String | — | — |
|
||||||
| context | 设置上下文环境,例如设置当前上下文就是 `_self`,父级就是 `$parent`,根组件 `$root`。优先读取 column 的 context 属性。 | Object | - | Table 所处上下文 |
|
| context | 设置上下文环境,例如设置当前上下文就是 `_self`,父级就是 `$parent`,根组件 `$root`。优先读取 column 的 context 属性。 | Object | - | Table 所处上下文 |
|
||||||
| empty-text | 空数据时显示的文本内容,也可以通过 `slot="empty"` 设置 | String | | - | 暂无数据 |
|
| empty-text | 空数据时显示的文本内容,也可以通过 `slot="empty"` 设置 | String | - | 暂无数据 |
|
||||||
|
| default-expand-all | 是否默认展开所有行,当 Table 中存在 type="expand" 的 Column 的时候有效 | Boolean | - | false |
|
||||||
|
| expand-row-keys | 可以通过该属性设置 Table 目前的展开行,需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。| Array | - | |
|
||||||
|
|
||||||
### Table Events
|
### Table Events
|
||||||
| 事件名 | 说明 | 参数 |
|
| 事件名 | 说明 | 参数 |
|
||||||
|
@ -1395,6 +1471,7 @@
|
||||||
| sort-change | 当表格的排序条件发生变化的时候会触发该事件 | { column, prop, order } |
|
| sort-change | 当表格的排序条件发生变化的时候会触发该事件 | { column, prop, order } |
|
||||||
| filter-change | 当表格的筛选条件发生变化的时候会触发该事件,参数的值是一个对象,对象的 key 是 column 的 columnKey,对应的 value 为用户选择的筛选条件的数组。 | filters |
|
| filter-change | 当表格的筛选条件发生变化的时候会触发该事件,参数的值是一个对象,对象的 key 是 column 的 columnKey,对应的 value 为用户选择的筛选条件的数组。 | filters |
|
||||||
| current-change | 当表格的当前行发生变化的时候会触发该事件,如果要高亮当前行,请打开表格的 highlight-current-row 属性 | currentRow, oldCurrentRow |
|
| current-change | 当表格的当前行发生变化的时候会触发该事件,如果要高亮当前行,请打开表格的 highlight-current-row 属性 | currentRow, oldCurrentRow |
|
||||||
|
| expand | 当用户对某一行展开或者关闭的上会触发该事件 | row, expanded |
|
||||||
|
|
||||||
### Table Methods
|
### Table Methods
|
||||||
| 方法名 | 说明 | 参数 |
|
| 方法名 | 说明 | 参数 |
|
||||||
|
@ -1405,7 +1482,7 @@
|
||||||
### Table-column Attributes
|
### Table-column Attributes
|
||||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||||
| type | 对应列的类型。如果设置了 `selection` 则显示多选框,如果设置了 `index` 则显示该行的索引(从 1 开始计算) | string | selection/index | — |
|
| type | 对应列的类型。如果设置了 `selection` 则显示多选框;如果设置了 `index` 则显示该行的索引(从 1 开始计算);如果设置了 expand 则显示为一个可展开的按钮 | string | selection/index/expand | — |
|
||||||
| column-key | column 的 key,如果需要使用 filter-change 事件,则需要此属性标识是哪个 column 的筛选条件 | string | - | - |
|
| column-key | column 的 key,如果需要使用 filter-change 事件,则需要此属性标识是哪个 column 的筛选条件 | string | - | - |
|
||||||
| label | 显示的标题 | string | — | — |
|
| label | 显示的标题 | string | — | — |
|
||||||
| prop | 对应列内容的字段名,也可以使用 property 属性 | string | — | — |
|
| prop | 对应列内容的字段名,也可以使用 property 属性 | string | — | — |
|
||||||
|
|
|
@ -38,7 +38,7 @@ export default {
|
||||||
<tbody>
|
<tbody>
|
||||||
{
|
{
|
||||||
this._l(this.data, (row, $index) =>
|
this._l(this.data, (row, $index) =>
|
||||||
<tr
|
[<tr
|
||||||
style={ this.rowStyle ? this.getRowStyle(row, $index) : null }
|
style={ this.rowStyle ? this.getRowStyle(row, $index) : null }
|
||||||
key={ this.$parent.rowKey ? this.getKeyOfRow(row, $index) : $index }
|
key={ this.$parent.rowKey ? this.getKeyOfRow(row, $index) : $index }
|
||||||
on-dblclick={ ($event) => this.handleDoubleClick($event, row) }
|
on-dblclick={ ($event) => this.handleDoubleClick($event, row) }
|
||||||
|
@ -46,7 +46,7 @@ export default {
|
||||||
on-contextmenu={ ($event) => this.handleContextMenu($event, row) }
|
on-contextmenu={ ($event) => this.handleContextMenu($event, row) }
|
||||||
on-mouseenter={ _ => this.handleMouseEnter($index) }
|
on-mouseenter={ _ => this.handleMouseEnter($index) }
|
||||||
on-mouseleave={ _ => this.handleMouseLeave() }
|
on-mouseleave={ _ => this.handleMouseLeave() }
|
||||||
class={ this.getRowClass(row, $index) }>
|
class={ [this.getRowClass(row, $index)] }>
|
||||||
{
|
{
|
||||||
this._l(this.columns, (column, cellIndex) =>
|
this._l(this.columns, (column, cellIndex) =>
|
||||||
<td
|
<td
|
||||||
|
@ -62,7 +62,15 @@ export default {
|
||||||
{
|
{
|
||||||
!this.fixed && this.layout.scrollY && this.layout.gutterWidth ? <td class="gutter" /> : ''
|
!this.fixed && this.layout.scrollY && this.layout.gutterWidth ? <td class="gutter" /> : ''
|
||||||
}
|
}
|
||||||
</tr>
|
</tr>,
|
||||||
|
this.store.states.expandRows.indexOf(row) > -1
|
||||||
|
? (<tr>
|
||||||
|
<td colspan={ this.columns.length } class="el-table__expanded-cell">
|
||||||
|
{ this.$parent.renderExpanded ? this.$parent.renderExpanded.call(this._renderProxy, h, { row, $index, store: this.store, _self: this.$parent.$vnode.context }) : ''}
|
||||||
|
</td>
|
||||||
|
</tr>)
|
||||||
|
: ''
|
||||||
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -178,7 +186,7 @@ export default {
|
||||||
|
|
||||||
if (cell) {
|
if (cell) {
|
||||||
const column = getColumnByCell(table, cell);
|
const column = getColumnByCell(table, cell);
|
||||||
const hoverState = table.hoverState = { cell, column, row };
|
const hoverState = table.hoverState = {cell, column, row};
|
||||||
table.$emit('cell-mouse-enter', hoverState.row, hoverState.column, hoverState.cell, event);
|
table.$emit('cell-mouse-enter', hoverState.row, hoverState.column, hoverState.cell, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +236,10 @@ export default {
|
||||||
this.store.commit('setCurrentRow', row);
|
this.store.commit('setCurrentRow', row);
|
||||||
|
|
||||||
table.$emit('row-click', row, event, column);
|
table.$emit('row-click', row, event, column);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleExpandClick(row) {
|
||||||
|
this.store.commit('toggleRowExpanded', row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,12 @@ const defaults = {
|
||||||
order: '',
|
order: '',
|
||||||
className: 'el-table-column--selection'
|
className: 'el-table-column--selection'
|
||||||
},
|
},
|
||||||
|
expand: {
|
||||||
|
width: 48,
|
||||||
|
minWidth: 48,
|
||||||
|
realWidth: 48,
|
||||||
|
order: ''
|
||||||
|
},
|
||||||
index: {
|
index: {
|
||||||
width: 48,
|
width: 48,
|
||||||
minWidth: 48,
|
minWidth: 48,
|
||||||
|
@ -48,6 +54,21 @@ const forced = {
|
||||||
return <div>{ $index + 1 }</div>;
|
return <div>{ $index + 1 }</div>;
|
||||||
},
|
},
|
||||||
sortable: false
|
sortable: false
|
||||||
|
},
|
||||||
|
expand: {
|
||||||
|
renderHeader: function(h, {}) {
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
renderCell: function(h, { row, store }, proxy) {
|
||||||
|
const expanded = store.states.expandRows.indexOf(row) > -1;
|
||||||
|
return <div class={ 'el-table__expand-icon ' + (expanded ? 'el-table__expand-icon--expanded' : '') }
|
||||||
|
on-click={ () => proxy.handleExpandClick(row) }>
|
||||||
|
<i class='el-icon el-icon-arrow-right'></i>
|
||||||
|
</div>;
|
||||||
|
},
|
||||||
|
sortable: false,
|
||||||
|
resizable: false,
|
||||||
|
className: 'el-table__expand-column'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -225,9 +246,35 @@ export default {
|
||||||
|
|
||||||
objectAssign(column, forced[type] || {});
|
objectAssign(column, forced[type] || {});
|
||||||
|
|
||||||
|
this.columnConfig = column;
|
||||||
|
|
||||||
let renderCell = column.renderCell;
|
let renderCell = column.renderCell;
|
||||||
let _self = this;
|
let _self = this;
|
||||||
|
|
||||||
|
if (type === 'expand') {
|
||||||
|
owner.renderExpanded = function(h, data) {
|
||||||
|
if (_self.$vnode.data.inlineTemplate) {
|
||||||
|
data._self = _self.context || data._self;
|
||||||
|
if (Object.prototype.toString.call(data._self) === '[object Object]') {
|
||||||
|
for (let prop in data._self) {
|
||||||
|
if (!data.hasOwnProperty(prop)) {
|
||||||
|
data[prop] = data._self[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data._staticTrees = _self._staticTrees;
|
||||||
|
data.$options.staticRenderFns = _self.$options.staticRenderFns;
|
||||||
|
return _self.customRender.call(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
column.renderCell = function(h, data) {
|
||||||
|
return <div class="cell">{ renderCell(h, data, this._renderProxy) }</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
column.renderCell = function(h, data) {
|
column.renderCell = function(h, data) {
|
||||||
if (_self.$vnode.data.inlineTemplate) {
|
if (_self.$vnode.data.inlineTemplate) {
|
||||||
renderCell = function() {
|
renderCell = function() {
|
||||||
|
@ -261,8 +308,6 @@ export default {
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
: <div class="cell">{ renderCell(h, data) }</div>;
|
: <div class="cell">{ renderCell(h, data) }</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.columnConfig = column;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
destroyed() {
|
destroyed() {
|
||||||
|
|
|
@ -69,7 +69,9 @@ const TableStore = function(table, initialState = {}) {
|
||||||
selectable: null,
|
selectable: null,
|
||||||
currentRow: null,
|
currentRow: null,
|
||||||
hoverRow: null,
|
hoverRow: null,
|
||||||
filters: {}
|
filters: {},
|
||||||
|
expandRows: [],
|
||||||
|
defaultExpandAll: false
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let prop in initialState) {
|
for (let prop in initialState) {
|
||||||
|
@ -85,6 +87,15 @@ TableStore.prototype.mutations = {
|
||||||
states._data = data;
|
states._data = data;
|
||||||
states.data = sortData((data || []), states);
|
states.data = sortData((data || []), states);
|
||||||
|
|
||||||
|
states.data.forEach((item) => {
|
||||||
|
if (!item.$extra) {
|
||||||
|
Object.defineProperty(item, '$extra', {
|
||||||
|
value: {},
|
||||||
|
enumerable: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.updateCurrentRow();
|
this.updateCurrentRow();
|
||||||
|
|
||||||
if (!states.reserveSelection) {
|
if (!states.reserveSelection) {
|
||||||
|
@ -114,6 +125,11 @@ TableStore.prototype.mutations = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultExpandAll = states.defaultExpandAll;
|
||||||
|
if (defaultExpandAll) {
|
||||||
|
this.states.expandRows = (states.data || []).slice(0);
|
||||||
|
}
|
||||||
|
|
||||||
Vue.nextTick(() => this.table.updateScrollY());
|
Vue.nextTick(() => this.table.updateScrollY());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -218,6 +234,26 @@ TableStore.prototype.mutations = {
|
||||||
this.updateAllSelected();
|
this.updateAllSelected();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
toggleRowExpanded: function(states, row, expanded) {
|
||||||
|
const expandRows = states.expandRows;
|
||||||
|
if (typeof expanded !== 'undefined') {
|
||||||
|
const index = expandRows.indexOf(row);
|
||||||
|
if (expanded) {
|
||||||
|
if (index === -1) expandRows.push(row);
|
||||||
|
} else {
|
||||||
|
if (index !== -1) expandRows.splice(index, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const index = expandRows.indexOf(row);
|
||||||
|
if (index === -1) {
|
||||||
|
expandRows.push(row);
|
||||||
|
} else {
|
||||||
|
expandRows.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.table.$emit('expand', row, expandRows.indexOf(row) !== -1);
|
||||||
|
},
|
||||||
|
|
||||||
toggleAllSelection: debounce(10, function(states) {
|
toggleAllSelection: debounce(10, function(states) {
|
||||||
const data = states.data || [];
|
const data = states.data || [];
|
||||||
const value = !states.isAllSelected;
|
const value = !states.isAllSelected;
|
||||||
|
@ -286,6 +322,22 @@ TableStore.prototype.clearSelection = function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TableStore.prototype.setExpandRowKeys = function(rowKeys) {
|
||||||
|
const expandRows = [];
|
||||||
|
const data = this.states.data;
|
||||||
|
const rowKey = this.states.rowKey;
|
||||||
|
if (!rowKey) throw new Error('[Table] prop row-key should not be empty.');
|
||||||
|
const keysMap = getKeysMap(data, rowKey);
|
||||||
|
rowKeys.forEach((key) => {
|
||||||
|
const info = keysMap[key];
|
||||||
|
if (info) {
|
||||||
|
expandRows.push(info.row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.states.expandRows = expandRows;
|
||||||
|
};
|
||||||
|
|
||||||
TableStore.prototype.toggleRowSelection = function(row, selected) {
|
TableStore.prototype.toggleRowSelection = function(row, selected) {
|
||||||
const changed = toggleRowSelection(this.states, row, selected);
|
const changed = toggleRowSelection(this.states, row, selected);
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
@ -395,6 +447,8 @@ TableStore.prototype.commit = function(name, ...args) {
|
||||||
const mutations = this.mutations;
|
const mutations = this.mutations;
|
||||||
if (mutations[name]) {
|
if (mutations[name]) {
|
||||||
mutations[name].apply(this, [this.states].concat(args));
|
mutations[name].apply(this, [this.states].concat(args));
|
||||||
|
} else {
|
||||||
|
throw new Error(`Action not found: ${name}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,11 @@
|
||||||
|
|
||||||
highlightCurrentRow: Boolean,
|
highlightCurrentRow: Boolean,
|
||||||
|
|
||||||
emptyText: String
|
emptyText: String,
|
||||||
|
|
||||||
|
expandRowKeys: Array,
|
||||||
|
|
||||||
|
defaultExpandAll: Boolean
|
||||||
},
|
},
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
|
@ -346,6 +350,10 @@
|
||||||
handler(val) {
|
handler(val) {
|
||||||
this.store.commit('setData', val);
|
this.store.commit('setData', val);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
expandRowKeys(newVal) {
|
||||||
|
this.store.setExpandRowKeys(newVal);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -362,7 +370,8 @@
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
const store = new TableStore(this, {
|
const store = new TableStore(this, {
|
||||||
rowKey: this.rowKey
|
rowKey: this.rowKey,
|
||||||
|
defaultExpandAll: this.defaultExpandAll
|
||||||
});
|
});
|
||||||
const layout = new TableLayout({
|
const layout = new TableLayout({
|
||||||
store,
|
store,
|
||||||
|
@ -373,6 +382,7 @@
|
||||||
return {
|
return {
|
||||||
store,
|
store,
|
||||||
layout,
|
layout,
|
||||||
|
renderExpanded: null,
|
||||||
resizeProxyVisible: false
|
resizeProxyVisible: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,44 @@
|
||||||
color: #5e6d82;
|
color: #5e6d82;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@e expand-column {
|
||||||
|
.cell {
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@e expand-icon {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #666;
|
||||||
|
font-size: 12px;
|
||||||
|
transition: transform 0.2s ease-in-out;
|
||||||
|
height: 40px;
|
||||||
|
|
||||||
|
@m expanded {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
> .el-icon {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
margin-left: -5px;
|
||||||
|
margin-top: -5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@e expanded-cell {
|
||||||
|
padding: 20px 50px;
|
||||||
|
background-color: #f9fafc;
|
||||||
|
box-shadow: inset 0 2px 0 #f4f4f4;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f9fafc !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@modifier fit {
|
@modifier fit {
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
|
|
|
@ -8,11 +8,11 @@ const toArray = function(obj) {
|
||||||
|
|
||||||
const getTestData = function() {
|
const getTestData = function() {
|
||||||
return [
|
return [
|
||||||
{ name: 'Toy Story', release: '1995-11-22', director: 'John Lasseter', runtime: 80 },
|
{ id: 1, name: 'Toy Story', release: '1995-11-22', director: 'John Lasseter', runtime: 80 },
|
||||||
{ name: 'A Bug\'s Life', release: '1998-11-25', director: 'John Lasseter', runtime: 95 },
|
{ id: 2, name: 'A Bug\'s Life', release: '1998-11-25', director: 'John Lasseter', runtime: 95 },
|
||||||
{ name: 'Toy Story 2', release: '1999-11-24', director: 'John Lasseter', runtime: 92 },
|
{ id: 3, name: 'Toy Story 2', release: '1999-11-24', director: 'John Lasseter', runtime: 92 },
|
||||||
{ name: 'Monsters, Inc.', release: '2001-11-2', director: 'Peter Docter', runtime: 92 },
|
{ id: 4, name: 'Monsters, Inc.', release: '2001-11-2', director: 'Peter Docter', runtime: 92 },
|
||||||
{ name: 'Finding Nemo', release: '2003-5-30', director: 'Andrew Stanton', runtime: 100 }
|
{ id: 5, name: 'Finding Nemo', release: '2003-5-30', director: 'Andrew Stanton', runtime: 100 }
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ describe('Table', () => {
|
||||||
const vm = createVue({
|
const vm = createVue({
|
||||||
template: `
|
template: `
|
||||||
<el-table :data="testData">
|
<el-table :data="testData">
|
||||||
|
<el-table-column prop="id" />
|
||||||
<el-table-column prop="name" label="片名" />
|
<el-table-column prop="name" label="片名" />
|
||||||
<el-table-column prop="release" label="发行日期" />
|
<el-table-column prop="release" label="发行日期" />
|
||||||
<el-table-column prop="director" label="导演" />
|
<el-table-column prop="director" label="导演" />
|
||||||
|
@ -957,6 +958,90 @@ describe('Table', () => {
|
||||||
}, DELAY);
|
}, DELAY);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('= expand', () => {
|
||||||
|
const createInstance = function(extra) {
|
||||||
|
extra = extra || '';
|
||||||
|
return createVue({
|
||||||
|
template: `
|
||||||
|
<el-table row-key="id" :data="testData" @expand="handleExpand" ${extra}>
|
||||||
|
<el-table-column type="expand" inline-template>
|
||||||
|
<div>{{row.name}}</div>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="release" label="release" />
|
||||||
|
<el-table-column prop="director" label="director" />
|
||||||
|
<el-table-column prop="runtime" label="runtime" />
|
||||||
|
</el-table>
|
||||||
|
`,
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.testData = getTestData();
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return { expandCount: 0, expandRowKeys: [] };
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleExpand() {
|
||||||
|
this.expandCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
it('works', done => {
|
||||||
|
const vm = createInstance();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.$el.querySelectorAll('td.el-table__expand-column').length).to.equal(5);
|
||||||
|
destroyVM(vm);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should expand when click icon', done => {
|
||||||
|
const vm = createInstance();
|
||||||
|
setTimeout(_ => {
|
||||||
|
vm.$el.querySelector('td.el-table__expand-column .el-table__expand-icon').click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.$el.querySelectorAll('.el-table__expanded-cell').length).to.equal(1);
|
||||||
|
expect(vm.expandCount).to.equal(1);
|
||||||
|
vm.$el.querySelector('td.el-table__expand-column .el-table__expand-icon').click();
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.$el.querySelectorAll('.el-table__expanded-cell').length).to.equal(0);
|
||||||
|
expect(vm.expandCount).to.equal(2);
|
||||||
|
destroyVM(vm);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set expanded rows using expandRowKeys', done => {
|
||||||
|
const vm = createInstance(':expand-row-keys="expandRowKeys"');
|
||||||
|
setTimeout(_ => {
|
||||||
|
vm.expandRowKeys = [1, 3];
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.$el.querySelectorAll('.el-table__expanded-cell').length).to.equal(2);
|
||||||
|
vm.expandRowKeys = [2];
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.$el.querySelectorAll('.el-table__expanded-cell').length).to.equal(1);
|
||||||
|
destroyVM(vm);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should default-expand-all when default-expand-all is true', done => {
|
||||||
|
const vm = createInstance('default-expand-all');
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.$el.querySelectorAll('.el-table__expanded-cell').length).to.equal(5);
|
||||||
|
destroyVM(vm);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('sortable', () => {
|
describe('sortable', () => {
|
||||||
|
|
Loading…
Reference in New Issue