Преглед на файлове

Feature table maxHeight (#1560) (#1674)

* :sparkles: [Table] Added fluid height table with maxHeight prop (#1560)

* :rotating_light: [Table] Added test for maxHeight prop (#1560)

* :books: [Table] Added the documentation of fluid-height table (#1560)
Hashem Qolami преди 8 години
родител
ревизия
998dcce225
променени са 5 файла, в които са добавени 282 реда и са изтрити 31 реда
  1. 176 1
      examples/docs/en-US/table.md
  2. 12 11
      packages/table/src/table-layout.js
  3. 77 19
      packages/table/src/table.vue
  4. 8 0
      packages/theme-default/src/table.css
  5. 9 0
      test/unit/specs/table.spec.js

+ 176 - 1
examples/docs/en-US/table.md

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

+ 12 - 11
packages/table/src/table-layout.js

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

+ 77 - 19
packages/table/src/table.vue

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

+ 8 - 0
packages/theme-default/src/table.css

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

+ 9 - 0
test/unit/specs/table.spec.js

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