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)
pull/1660/merge
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', 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 |

View File

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

View File

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

View File

@ -388,5 +388,13 @@
background-color: #eff2f7; 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); }, 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(_ => {