Feature table maxHeight (#1560) (#1674)

*  [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:
Hashem Qolami 2016-12-13 11:51:59 +03:30 committed by cinwell.li
parent b9f7e10f20
commit 998dcce225
5 changed files with 282 additions and 31 deletions

View File

@ -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 |

View File

@ -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() {

View File

@ -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;
}
},

View File

@ -388,5 +388,13 @@
background-color: #eff2f7;
}
}
@modifier fluid-height {
.el-table__fixed,
.el-table__fixed-right {
bottom: 0;
overflow: hidden;
}
}
}
}

View File

@ -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(_ => {