mirror of https://github.com/ElemeFE/element
* ✨ [Table] Added fluid height table with maxHeight prop (#1560) * 🚨 [Table] Added test for maxHeight prop (#1560) * 📚 [Table] Added the documentation of fluid-height table (#1560)pull/1660/merge
parent
b9f7e10f20
commit
998dcce225
|
@ -104,6 +104,49 @@
|
||||||
address: 'No. 189, Grove St, Los Angeles',
|
address: 'No. 189, Grove St, Los Angeles',
|
||||||
zip: 'CA 90036'
|
zip: 'CA 90036'
|
||||||
}],
|
}],
|
||||||
|
tableData4: [{
|
||||||
|
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'
|
||||||
|
}],
|
||||||
currentRow: null,
|
currentRow: null,
|
||||||
multipleSelection: []
|
multipleSelection: []
|
||||||
};
|
};
|
||||||
|
@ -144,6 +187,10 @@
|
||||||
return 'positive-row';
|
return 'positive-row';
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteRow(index, rows) {
|
||||||
|
rows.splice(index, 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -683,6 +730,133 @@ When you have huge chunks of data to put in a table, you can fix the header and
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### Fluid-height Table with fixed header (and columns)
|
||||||
|
|
||||||
|
When the the data is dynamically changed, you might want the table to have a maximum height rather than a fixed height and to show the scroll bar if needed.
|
||||||
|
|
||||||
|
:::demo By setting the attribute `maxHeight` of `el-table`, you can fix the table header. The table body scrolls only if the height of the rows exceeds the maxHeight value.
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<el-table
|
||||||
|
:data="tableData4"
|
||||||
|
border
|
||||||
|
style="width: 100%"
|
||||||
|
max-height="250">
|
||||||
|
<el-table-column
|
||||||
|
fixed
|
||||||
|
prop="date"
|
||||||
|
label="Date"
|
||||||
|
width="150">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="name"
|
||||||
|
label="Name"
|
||||||
|
width="120">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="state"
|
||||||
|
label="State"
|
||||||
|
width="120">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="city"
|
||||||
|
label="City"
|
||||||
|
width="120">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="address"
|
||||||
|
label="Address"
|
||||||
|
width="300">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="zip"
|
||||||
|
label="Zip"
|
||||||
|
width="120">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
inline-template
|
||||||
|
:context="_self"
|
||||||
|
fixed="right"
|
||||||
|
label="Operations"
|
||||||
|
width="120">
|
||||||
|
<span>
|
||||||
|
<el-button
|
||||||
|
@click.native.prevent="deleteRow($index, tableData4)"
|
||||||
|
type="text"
|
||||||
|
size="small">
|
||||||
|
Remove
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
deleteRow(index, rows) {
|
||||||
|
rows.splice(index, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableData4: [{
|
||||||
|
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>
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
|
||||||
### Grouping table head
|
### Grouping table head
|
||||||
|
|
||||||
When the data structure is complex, you can use group header to show the data hierarchy.
|
When the data structure is complex, you can use group header to show the data hierarchy.
|
||||||
|
@ -1177,7 +1351,8 @@ Customize table column so it can be integrated with other components.
|
||||||
| Attribute | Description | Type | Accepted Values | Default |
|
| Attribute | Description | Type | Accepted Values | Default |
|
||||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||||
| data | table data | array | — | — |
|
| data | table data | array | — | — |
|
||||||
| height | Table's height. By default it has an auto height. If its value is a number, the height is measured in pixels; if its value is a string, the height is affected by external styles | string/number | — | — |
|
| height | Table's height. By default it has an `auto` height. If its value is a number, the height is measured in pixels; if its value is a string, the height is affected by external styles | string/number | — | — |
|
||||||
|
| maxHeight | Table's max-height. The height of the table starts from `auto` until it reaches the maxHeight limit. The `maxHeight` is measured in pixels, same as `height` | string/number | — | — |
|
||||||
| stripe | whether table is striped | boolean | — | false |
|
| stripe | whether table is striped | boolean | — | false |
|
||||||
| border | whether table has vertical border | boolean | — | false |
|
| border | whether table has vertical border | boolean | — | false |
|
||||||
| fit | whether width of column automatically fits its container | boolean | — | true |
|
| fit | whether width of column automatically fits its container | boolean | — | true |
|
||||||
|
|
|
@ -51,26 +51,28 @@ class TableLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setHeight(height) {
|
setHeight(value, prop = 'height') {
|
||||||
const el = this.table.$el;
|
const el = this.table.$el;
|
||||||
if (typeof height === 'string') {
|
if (typeof value === 'string' && /^\d+$/.test(value)) {
|
||||||
if (/^\d+$/.test(height)) {
|
value = Number(value);
|
||||||
height = Number(height);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.height = height;
|
this.height = value;
|
||||||
|
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
if (!isNaN(height)) {
|
if (typeof value === 'number') {
|
||||||
el.style.height = height + 'px';
|
el.style[prop] = value + 'px';
|
||||||
|
|
||||||
this.updateHeight();
|
this.updateHeight();
|
||||||
} else if (typeof height === 'string') {
|
} else if (typeof value === 'string') {
|
||||||
this.updateHeight();
|
this.updateHeight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setMaxHeight(value) {
|
||||||
|
return this.setHeight(value, 'max-height');
|
||||||
|
}
|
||||||
|
|
||||||
updateHeight() {
|
updateHeight() {
|
||||||
const height = this.tableHeight = this.table.$el.clientHeight;
|
const height = this.tableHeight = this.table.$el.clientHeight;
|
||||||
const { headerWrapper } = this.table.$refs;
|
const { headerWrapper } = this.table.$refs;
|
||||||
|
@ -81,7 +83,6 @@ class TableLayout {
|
||||||
this.bodyHeight = height;
|
this.bodyHeight = height;
|
||||||
}
|
}
|
||||||
this.fixedBodyHeight = this.scrollX ? height - this.gutterWidth : height;
|
this.fixedBodyHeight = this.scrollX ? height - this.gutterWidth : height;
|
||||||
this.viewportHeight = this.scrollX ? height - this.gutterWidth : height;
|
|
||||||
} else {
|
} else {
|
||||||
const headerHeight = this.headerHeight = headerWrapper.offsetHeight;
|
const headerHeight = this.headerHeight = headerWrapper.offsetHeight;
|
||||||
const bodyHeight = height - headerHeight;
|
const bodyHeight = height - headerHeight;
|
||||||
|
@ -89,8 +90,8 @@ class TableLayout {
|
||||||
this.bodyHeight = bodyHeight;
|
this.bodyHeight = bodyHeight;
|
||||||
}
|
}
|
||||||
this.fixedBodyHeight = this.scrollX ? bodyHeight - this.gutterWidth : bodyHeight;
|
this.fixedBodyHeight = this.scrollX ? bodyHeight - this.gutterWidth : bodyHeight;
|
||||||
this.viewportHeight = this.scrollX ? height - this.gutterWidth : height;
|
|
||||||
}
|
}
|
||||||
|
this.viewportHeight = this.scrollX ? height - this.gutterWidth : height;
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
'el-table--fit': fit,
|
'el-table--fit': fit,
|
||||||
'el-table--striped': stripe,
|
'el-table--striped': stripe,
|
||||||
'el-table--border': border,
|
'el-table--border': border,
|
||||||
|
'el-table--fluid-height': maxHeight,
|
||||||
'el-table--enable-row-hover': !store.states.isComplex,
|
'el-table--enable-row-hover': !store.states.isComplex,
|
||||||
'el-table--enable-row-transition': true || (store.states.data || []).length !== 0 && (store.states.data || []).length < 100
|
'el-table--enable-row-transition': true || (store.states.data || []).length !== 0 && (store.states.data || []).length < 100
|
||||||
}"
|
}"
|
||||||
|
@ -17,8 +18,7 @@
|
||||||
:style="{ width: layout.bodyWidth ? layout.bodyWidth + 'px' : '' }">
|
:style="{ width: layout.bodyWidth ? layout.bodyWidth + 'px' : '' }">
|
||||||
</table-header>
|
</table-header>
|
||||||
</div>
|
</div>
|
||||||
<div class="el-table__body-wrapper" ref="bodyWrapper"
|
<div class="el-table__body-wrapper" ref="bodyWrapper" :style="[bodyHeight]">
|
||||||
:style="{ height: layout.bodyHeight ? layout.bodyHeight + 'px' : '' }">
|
|
||||||
<table-body
|
<table-body
|
||||||
:context="context"
|
:context="context"
|
||||||
:store="store"
|
:store="store"
|
||||||
|
@ -34,10 +34,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="el-table__fixed" ref="fixedWrapper"
|
<div class="el-table__fixed" ref="fixedWrapper"
|
||||||
v-if="fixedColumns.length > 0"
|
v-if="fixedColumns.length > 0"
|
||||||
:style="{
|
:style="[
|
||||||
width: layout.fixedWidth ? layout.fixedWidth + 'px' : '',
|
{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' },
|
||||||
height: layout.viewportHeight ? layout.viewportHeight + 'px' : ''
|
fixedHeight
|
||||||
}">
|
]">
|
||||||
<div class="el-table__fixed-header-wrapper" ref="fixedHeaderWrapper" v-if="showHeader">
|
<div class="el-table__fixed-header-wrapper" ref="fixedHeaderWrapper" v-if="showHeader">
|
||||||
<table-header
|
<table-header
|
||||||
fixed="left"
|
fixed="left"
|
||||||
|
@ -47,10 +47,10 @@
|
||||||
:style="{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' }"></table-header>
|
:style="{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' }"></table-header>
|
||||||
</div>
|
</div>
|
||||||
<div class="el-table__fixed-body-wrapper" ref="fixedBodyWrapper"
|
<div class="el-table__fixed-body-wrapper" ref="fixedBodyWrapper"
|
||||||
:style="{
|
:style="[
|
||||||
top: layout.headerHeight + 'px',
|
{ top: layout.headerHeight + 'px' },
|
||||||
height: layout.fixedBodyHeight ? layout.fixedBodyHeight + 'px' : ''
|
fixedBodyHeight
|
||||||
}">
|
]">
|
||||||
<table-body
|
<table-body
|
||||||
fixed="left"
|
fixed="left"
|
||||||
:store="store"
|
:store="store"
|
||||||
|
@ -64,11 +64,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="el-table__fixed-right" ref="rightFixedWrapper"
|
<div class="el-table__fixed-right" ref="rightFixedWrapper"
|
||||||
v-if="rightFixedColumns.length > 0"
|
v-if="rightFixedColumns.length > 0"
|
||||||
:style="{
|
:style="[
|
||||||
width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '',
|
{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' },
|
||||||
height: layout.viewportHeight ? layout.viewportHeight + 'px' : '',
|
{ right: layout.scrollY ? (border ? layout.gutterWidth : (layout.gutterWidth || 1)) + 'px' : '' },
|
||||||
right: layout.scrollY ? (border ? layout.gutterWidth : (layout.gutterWidth || 1)) + 'px' : ''
|
fixedHeight
|
||||||
}">
|
]">
|
||||||
<div class="el-table__fixed-header-wrapper" ref="rightFixedHeaderWrapper" v-if="showHeader">
|
<div class="el-table__fixed-header-wrapper" ref="rightFixedHeaderWrapper" v-if="showHeader">
|
||||||
<table-header
|
<table-header
|
||||||
fixed="right"
|
fixed="right"
|
||||||
|
@ -78,10 +78,10 @@
|
||||||
:style="{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' }"></table-header>
|
:style="{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' }"></table-header>
|
||||||
</div>
|
</div>
|
||||||
<div class="el-table__fixed-body-wrapper" ref="rightFixedBodyWrapper"
|
<div class="el-table__fixed-body-wrapper" ref="rightFixedBodyWrapper"
|
||||||
:style="{
|
:style="[
|
||||||
top: layout.headerHeight + 'px',
|
{ top: layout.headerHeight + 'px' },
|
||||||
height: layout.fixedBodyHeight ? layout.fixedBodyHeight + 'px' : ''
|
fixedBodyHeight
|
||||||
}">
|
]">
|
||||||
<table-body
|
<table-body
|
||||||
fixed="right"
|
fixed="right"
|
||||||
:store="store"
|
:store="store"
|
||||||
|
@ -132,6 +132,8 @@
|
||||||
|
|
||||||
height: [String, Number],
|
height: [String, Number],
|
||||||
|
|
||||||
|
maxHeight: [String, Number],
|
||||||
|
|
||||||
fit: {
|
fit: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
@ -238,6 +240,8 @@
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (this.height) {
|
if (this.height) {
|
||||||
this.layout.setHeight(this.height);
|
this.layout.setHeight(this.height);
|
||||||
|
} else if (this.maxHeight) {
|
||||||
|
this.layout.setMaxHeight(this.maxHeight);
|
||||||
} else if (this.shouldUpdateHeight) {
|
} else if (this.shouldUpdateHeight) {
|
||||||
this.layout.updateHeight();
|
this.layout.updateHeight();
|
||||||
}
|
}
|
||||||
|
@ -275,6 +279,60 @@
|
||||||
|
|
||||||
rightFixedColumns() {
|
rightFixedColumns() {
|
||||||
return this.store.states.rightFixedColumns;
|
return this.store.states.rightFixedColumns;
|
||||||
|
},
|
||||||
|
|
||||||
|
bodyHeight() {
|
||||||
|
let style = {};
|
||||||
|
|
||||||
|
if (this.height) {
|
||||||
|
style = {
|
||||||
|
height: this.layout.bodyHeight ? this.layout.bodyHeight + 'px' : ''
|
||||||
|
};
|
||||||
|
} else if (this.maxHeight) {
|
||||||
|
style = {
|
||||||
|
'max-height': (this.showHeader ? this.maxHeight - this.layout.headerHeight : this.maxHeight) + 'px'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
|
||||||
|
fixedBodyHeight() {
|
||||||
|
let style = {};
|
||||||
|
|
||||||
|
if (this.height) {
|
||||||
|
style = {
|
||||||
|
height: this.layout.fixedBodyHeight ? this.layout.fixedBodyHeight + 'px' : ''
|
||||||
|
};
|
||||||
|
} else if (this.maxHeight) {
|
||||||
|
let maxHeight = this.layout.scrollX ? this.maxHeight - this.layout.gutterWidth : this.maxHeight;
|
||||||
|
|
||||||
|
if (this.showHeader) {
|
||||||
|
maxHeight -= this.layout.headerHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
style = {
|
||||||
|
'max-height': maxHeight + 'px'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
|
||||||
|
fixedHeight() {
|
||||||
|
let style = {};
|
||||||
|
|
||||||
|
if (this.maxHeight) {
|
||||||
|
style = {
|
||||||
|
bottom: (this.layout.scrollX && this.data.length) ? this.layout.gutterWidth + 'px' : ''
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
style = {
|
||||||
|
height: this.layout.viewportHeight ? this.layout.viewportHeight + 'px' : ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return style;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -388,5 +388,13 @@
|
||||||
background-color: #eff2f7;
|
background-color: #eff2f7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@modifier fluid-height {
|
||||||
|
.el-table__fixed,
|
||||||
|
.el-table__fixed-right {
|
||||||
|
bottom: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,15 @@ describe('Table', () => {
|
||||||
}, DELAY);
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('maxHeight', done => {
|
||||||
|
const vm = createTable('max-height="134"');
|
||||||
|
setTimeout(_ => {
|
||||||
|
expect(vm.$el.style.maxHeight).to.equal('134px');
|
||||||
|
destroyVM(vm);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
|
||||||
it('stripe', done => {
|
it('stripe', done => {
|
||||||
const vm = createTable('stripe');
|
const vm = createTable('stripe');
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
|
|
Loading…
Reference in New Issue