Commit 998dcce2 authored by Hashem Qolami's avatar Hashem Qolami Committed by cinwell.li

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)
parent b9f7e10f
...@@ -104,6 +104,49 @@ ...@@ -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 @@ ...@@ -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 ...@@ -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. ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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', () => { ...@@ -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(_ => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment