mirror of
https://gitee.com/ElemeFE/element.git
synced 2024-12-02 04:08:10 +08:00
* ✨ [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)
This commit is contained in:
parent
b9f7e10f20
commit
998dcce225
@ -104,6 +104,49 @@
|
||||
address: 'No. 189, Grove St, Los Angeles',
|
||||
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,
|
||||
multipleSelection: []
|
||||
};
|
||||
@ -144,6 +187,10 @@
|
||||
return 'positive-row';
|
||||
}
|
||||
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
|
||||
|
||||
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 |
|
||||
|---------- |-------------- |---------- |-------------------------------- |-------- |
|
||||
| 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 |
|
||||
| border | whether table has vertical border | boolean | — | false |
|
||||
| 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;
|
||||
if (typeof height === 'string') {
|
||||
if (/^\d+$/.test(height)) {
|
||||
height = Number(height);
|
||||
}
|
||||
if (typeof value === 'string' && /^\d+$/.test(value)) {
|
||||
value = Number(value);
|
||||
}
|
||||
|
||||
this.height = height;
|
||||
this.height = value;
|
||||
|
||||
if (!el) return;
|
||||
if (!isNaN(height)) {
|
||||
el.style.height = height + 'px';
|
||||
if (typeof value === 'number') {
|
||||
el.style[prop] = value + 'px';
|
||||
|
||||
this.updateHeight();
|
||||
} else if (typeof height === 'string') {
|
||||
} else if (typeof value === 'string') {
|
||||
this.updateHeight();
|
||||
}
|
||||
}
|
||||
|
||||
setMaxHeight(value) {
|
||||
return this.setHeight(value, 'max-height');
|
||||
}
|
||||
|
||||
updateHeight() {
|
||||
const height = this.tableHeight = this.table.$el.clientHeight;
|
||||
const { headerWrapper } = this.table.$refs;
|
||||
@ -81,7 +83,6 @@ class TableLayout {
|
||||
this.bodyHeight = height;
|
||||
}
|
||||
this.fixedBodyHeight = this.scrollX ? height - this.gutterWidth : height;
|
||||
this.viewportHeight = this.scrollX ? height - this.gutterWidth : height;
|
||||
} else {
|
||||
const headerHeight = this.headerHeight = headerWrapper.offsetHeight;
|
||||
const bodyHeight = height - headerHeight;
|
||||
@ -89,8 +90,8 @@ class TableLayout {
|
||||
this.bodyHeight = 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() {
|
||||
|
@ -4,6 +4,7 @@
|
||||
'el-table--fit': fit,
|
||||
'el-table--striped': stripe,
|
||||
'el-table--border': border,
|
||||
'el-table--fluid-height': maxHeight,
|
||||
'el-table--enable-row-hover': !store.states.isComplex,
|
||||
'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' : '' }">
|
||||
</table-header>
|
||||
</div>
|
||||
<div class="el-table__body-wrapper" ref="bodyWrapper"
|
||||
:style="{ height: layout.bodyHeight ? layout.bodyHeight + 'px' : '' }">
|
||||
<div class="el-table__body-wrapper" ref="bodyWrapper" :style="[bodyHeight]">
|
||||
<table-body
|
||||
:context="context"
|
||||
:store="store"
|
||||
@ -34,10 +34,10 @@
|
||||
</div>
|
||||
<div class="el-table__fixed" ref="fixedWrapper"
|
||||
v-if="fixedColumns.length > 0"
|
||||
:style="{
|
||||
width: layout.fixedWidth ? layout.fixedWidth + 'px' : '',
|
||||
height: layout.viewportHeight ? layout.viewportHeight + 'px' : ''
|
||||
}">
|
||||
:style="[
|
||||
{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' },
|
||||
fixedHeight
|
||||
]">
|
||||
<div class="el-table__fixed-header-wrapper" ref="fixedHeaderWrapper" v-if="showHeader">
|
||||
<table-header
|
||||
fixed="left"
|
||||
@ -47,10 +47,10 @@
|
||||
:style="{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' }"></table-header>
|
||||
</div>
|
||||
<div class="el-table__fixed-body-wrapper" ref="fixedBodyWrapper"
|
||||
:style="{
|
||||
top: layout.headerHeight + 'px',
|
||||
height: layout.fixedBodyHeight ? layout.fixedBodyHeight + 'px' : ''
|
||||
}">
|
||||
:style="[
|
||||
{ top: layout.headerHeight + 'px' },
|
||||
fixedBodyHeight
|
||||
]">
|
||||
<table-body
|
||||
fixed="left"
|
||||
:store="store"
|
||||
@ -64,11 +64,11 @@
|
||||
</div>
|
||||
<div class="el-table__fixed-right" ref="rightFixedWrapper"
|
||||
v-if="rightFixedColumns.length > 0"
|
||||
:style="{
|
||||
width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '',
|
||||
height: layout.viewportHeight ? layout.viewportHeight + 'px' : '',
|
||||
right: layout.scrollY ? (border ? layout.gutterWidth : (layout.gutterWidth || 1)) + 'px' : ''
|
||||
}">
|
||||
:style="[
|
||||
{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' },
|
||||
{ right: layout.scrollY ? (border ? layout.gutterWidth : (layout.gutterWidth || 1)) + 'px' : '' },
|
||||
fixedHeight
|
||||
]">
|
||||
<div class="el-table__fixed-header-wrapper" ref="rightFixedHeaderWrapper" v-if="showHeader">
|
||||
<table-header
|
||||
fixed="right"
|
||||
@ -78,10 +78,10 @@
|
||||
:style="{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' }"></table-header>
|
||||
</div>
|
||||
<div class="el-table__fixed-body-wrapper" ref="rightFixedBodyWrapper"
|
||||
:style="{
|
||||
top: layout.headerHeight + 'px',
|
||||
height: layout.fixedBodyHeight ? layout.fixedBodyHeight + 'px' : ''
|
||||
}">
|
||||
:style="[
|
||||
{ top: layout.headerHeight + 'px' },
|
||||
fixedBodyHeight
|
||||
]">
|
||||
<table-body
|
||||
fixed="right"
|
||||
:store="store"
|
||||
@ -132,6 +132,8 @@
|
||||
|
||||
height: [String, Number],
|
||||
|
||||
maxHeight: [String, Number],
|
||||
|
||||
fit: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
@ -238,6 +240,8 @@
|
||||
this.$nextTick(() => {
|
||||
if (this.height) {
|
||||
this.layout.setHeight(this.height);
|
||||
} else if (this.maxHeight) {
|
||||
this.layout.setMaxHeight(this.maxHeight);
|
||||
} else if (this.shouldUpdateHeight) {
|
||||
this.layout.updateHeight();
|
||||
}
|
||||
@ -275,6 +279,60 @@
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@modifier fluid-height {
|
||||
.el-table__fixed,
|
||||
.el-table__fixed-right {
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -89,6 +89,15 @@ describe('Table', () => {
|
||||
}, 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 => {
|
||||
const vm = createTable('stripe');
|
||||
setTimeout(_ => {
|
||||
|
Loading…
Reference in New Issue
Block a user