Table support multiple table-head

This commit is contained in:
梁灏 2018-03-23 15:32:58 +08:00
parent 12739c33fa
commit 1acabf7912
5 changed files with 222 additions and 245 deletions

View file

@ -1,66 +1,91 @@
<template> <template>
<div> <div>
<Table border ref="selection" :columns="columns4" :data="data1" :height='258'></Table> <br><br><br><br><br>
<Button @click="handleSetData">Set Data</Button> <Table border :columns="columns1" height="500" :data="data1"></Table>
<Button @click="handleClearData">Clear Data</Button> <br><br><br><br><br>
<Button @click="handleSelectAll(true)">Set all selected</Button> <!--<Table width="550" height="200" border :columns="columns2" :data="data4"></Table>-->
<Button @click="handleSelectAll(false)">Cancel all selected</Button> <br><br><br><br><br>
<div style='margin:20px 0px'>
<Table border :columns="columns2" :data="data3"></Table>
</div>
<div style='margin:20px 0px'>
<Table :height='200' border :columns="columns2" :data="data3"></Table>
</div>
<div style='margin:20px 0px'>
<Table :width='600' border :columns="columns2" :data="data3"></Table>
</div>
<div style='margin:20px 0px'>
<Table :width='600' :height='200' border :columns="columns2" :data="data31"></Table>
</div>
<div style='margin:20px 0px;'>
Table scrolling <i-switch v-model="fixedHeader" style="margin-right: 5px"></i-switch>
<Table :data="tableData1" :columns="tableColumns1" :height="fixedHeader ? 250 : ''" stripe size='small'></Table>
<div style="margin: 10px;overflow: hidden">
<div style="float: right;">
<Page :total="100" show-sizer :current="1" @on-change="changePage"></Page>
</div>
</div>
</div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
data () { data () {
return { return {
columns4: [ columns1: [
{
type: 'selection',
width: 60,
align: 'center'
},
{ {
title: 'Name', title: 'Name',
key: 'name', key: 'name',
width: 260 align: 'center',
width: 200,
fixed: 'left'
}, },
{
title: 'Other',
align: 'center',
children: [
{ {
title: 'Age', title: 'Age',
key: 'age' key: 'age',
align: 'center',
width: 200
}, },
{ {
title: 'Address', title: 'Address',
key: 'address', align: 'center',
width: 260 children: [
{
title: 'Street',
key: 'street',
align: 'center',
width: 200
}, },
{ {
title: 'Address', title: 'Block',
key: 'address', align: 'center',
width: 260 children: [
{
title: 'Building',
key: 'building',
align: 'center',
width: 200
},
{
title: 'Door No.',
key: 'door',
align: 'center',
width: 200
}
]
}
]
}
]
},
{
title: 'Company',
align: 'center',
children: [
{
title: 'Company Address',
key: 'caddress',
align: 'center',
width: 200
},
{
title: 'Company Name',
key: 'cname',
align: 'center',
width: 200
}
]
},
{
title: 'Gender',
key: 'gender',
align: 'center',
width: 200,
fixed: 'right'
} }
],
data1: [
], ],
columns2: [ columns2: [
{ {
@ -72,7 +97,9 @@
{ {
title: 'Age', title: 'Age',
key: 'age', key: 'age',
width: 100 width: 100,
fixed: 'right',
sortable: true
}, },
{ {
title: 'Province', title: 'Province',
@ -92,8 +119,7 @@
{ {
title: 'Postcode', title: 'Postcode',
key: 'zip', key: 'zip',
width: 100, width: 100
fixed: 'right',
}, },
{ {
title: 'Action', title: 'Action',
@ -118,7 +144,8 @@
} }
} }
], ],
data3: [ data1: [],
data4: [
{ {
name: 'John Brown', name: 'John Brown',
age: 18, age: 18,
@ -151,16 +178,6 @@
city: 'Ottawa', city: 'Ottawa',
zip: 100000 zip: 100000
}, },
{
name: 'Jon Snow',
age: 26,
address: 'Ottawa No. 2 Lake Park',
province: 'Canada',
city: 'Ottawa',
zip: 100000
}
],
data31: [
{ {
name: 'John Brown', name: 'John Brown',
age: 18, age: 18,
@ -185,78 +202,6 @@
city: 'Sydney', city: 'Sydney',
zip: 100000 zip: 100000
}, },
{
name: 'Jon Snow',
age: 26,
address: 'Ottawa No. 2 Lake Park',
province: 'Canada',
city: 'Ottawa',
zip: 100000
},
{
name: 'Jon Snow',
age: 26,
address: 'Ottawa No. 2 Lake Park',
province: 'Canada',
city: 'Ottawa',
zip: 100000
},
{
name: 'Jim Green',
age: 24,
address: 'Washington, D.C. No. 1 Lake Park',
province: 'America',
city: 'Washington, D.C.',
zip: 100000
},
{
name: 'Joe Black',
age: 30,
address: 'Sydney No. 1 Lake Park',
province: 'Australian',
city: 'Sydney',
zip: 100000
},
{
name: 'Jon Snow',
age: 26,
address: 'Ottawa No. 2 Lake Park',
province: 'Canada',
city: 'Ottawa',
zip: 100000
},
{
name: 'Jon Snow',
age: 26,
address: 'Ottawa No. 2 Lake Park',
province: 'Canada',
city: 'Ottawa',
zip: 100000
},
{
name: 'Jim Green',
age: 24,
address: 'Washington, D.C. No. 1 Lake Park',
province: 'America',
city: 'Washington, D.C.',
zip: 100000
},
{
name: 'Joe Black',
age: 30,
address: 'Sydney No. 1 Lake Park',
province: 'Australian',
city: 'Sydney',
zip: 100000
},
{
name: 'Jon Snow',
age: 26,
address: 'Ottawa No. 2 Lake Park',
province: 'Canada',
city: 'Ottawa',
zip: 100000
},
{ {
name: 'Jon Snow', name: 'Jon Snow',
age: 26, age: 26,
@ -265,94 +210,25 @@
city: 'Ottawa', city: 'Ottawa',
zip: 100000 zip: 100000
} }
],
fixedHeader: false,
tableData1: [],
tableColumns1: [
{
title: 'Data1',
key: 'data1'
},
{
title: 'Data2',
key: 'data2'
},
{
title: 'Data3',
key: 'data3'
},
{
title: 'Data4',
key: 'data4'
},
{
title: 'Data5',
key: 'data5'
},
{
title: 'Data6Data6Data6Data6Data6Data6Data6Data6Data6Data6Data6',
key: 'data6'
},
] ]
} }
}, },
mounted(){ mounted () {
this.refreshData(); const data = [];
}, for (let i = 0; i < 100; i++) {
methods: {
handleSelectAll (status) {
this.$refs.selection.selectAll(status);
},
handleSetData () {
this.data1 = [
{
name: 'John Brown',
age: 18,
address: 'New York No. 1 Lake Park',
date: '2016-10-03'
},
{
name: 'Jim Green',
age: 24,
address: 'London No. 1 Lake Park',
date: '2016-10-01'
},
{
name: 'Joe Black',
age: 30,
address: 'Sydney No. 1 Lake Park',
date: '2016-10-02'
},
{
name: 'Jon Snow',
age: 26,
address: 'Ottawa No. 2 Lake Park',
date: '2016-10-04'
}
];
},
handleClearData () {
this.data1 = [];
},
refreshData(){
let data = [];
for (let i = 0; i < 10; i++) {
data.push({ data.push({
data1: Math.floor(Math.random () * 10000), key: i,
data2: Math.floor(Math.random () * 1000000), name: 'John Brown',
data3: Math.floor(Math.random () * 100000000), age: i + 1,
data4: Math.floor(Math.random () * Math.random () * 10000), street: 'Lake Park',
data5: Math.floor(Math.random () * Math.random () * 1000000), building: 'C',
data6: ''+Math.floor(Math.random () * Math.random () * 100000000)+Math.floor(Math.random () * 100000000)+Math.floor(Math.random () * 100000000), door: 2035,
caddress: 'Lake Street 42',
cname: 'SoftLake Co',
gender: 'M',
}); });
} }
this.tableData1 = data; this.data1 = data;
},
changePage(){
this.refreshData();
}
} }
} }
</script> </script>

View file

@ -4,8 +4,12 @@
<col v-for="(column, index) in columns" :width="setCellWidth(column, index, true)"> <col v-for="(column, index) in columns" :width="setCellWidth(column, index, true)">
</colgroup> </colgroup>
<thead> <thead>
<tr> <tr v-for="(cols, rowIndex) in headRows">
<th v-for="(column, index) in columns" :class="alignCls(column)"> <th
v-for="(column, index) in cols"
:colspan="column.colSpan"
:rowspan="column.rowSpan"
:class="alignCls(column)">
<div :class="cellClasses(column)"> <div :class="cellClasses(column)">
<template v-if="column.type === 'expand'"> <template v-if="column.type === 'expand'">
<span v-if="!column.renderHeader">{{ column.title || '' }}</span> <span v-if="!column.renderHeader">{{ column.title || '' }}</span>
@ -67,6 +71,7 @@
import renderHeader from './header'; import renderHeader from './header';
import Mixin from './mixin'; import Mixin from './mixin';
import Locale from '../../mixins/locale'; import Locale from '../../mixins/locale';
import { convertColumnOrder } from './util';
export default { export default {
name: 'TableHead', name: 'TableHead',
@ -82,7 +87,8 @@
fixed: { fixed: {
type: [Boolean, String], type: [Boolean, String],
default: false default: false
} },
columnRows: Array
}, },
computed: { computed: {
styles () { styles () {
@ -108,6 +114,25 @@
} }
return isSelectAll; return isSelectAll;
},
headRows () {
const isGroup = this.columnRows.length > 1;
return isGroup ? this.columnRows : [this.columns];
// if (isGroup) {
// const fixedType = this.fixed;
// if (fixedType) {
// if (fixedType === 'left') {
// return convertColumnOrder(this.columnRows, 'left');
// } else if (fixedType === 'right') {
// return convertColumnOrder(this.columnRows, 'right');
// }
// } else {
// return this.columnRows;
// }
// } else {
// return [this.columns];
// }
} }
}, },
methods: { methods: {

View file

@ -7,6 +7,7 @@
:prefix-cls="prefixCls" :prefix-cls="prefixCls"
:styleObject="tableStyle" :styleObject="tableStyle"
:columns="cloneColumns" :columns="cloneColumns"
:column-rows="columnRows"
:obj-data="objData" :obj-data="objData"
:columns-width="columnsWidth" :columns-width="columnsWidth"
:data="rebuildData"></table-head> :data="rebuildData"></table-head>
@ -43,6 +44,7 @@
:prefix-cls="prefixCls" :prefix-cls="prefixCls"
:styleObject="fixedTableStyle" :styleObject="fixedTableStyle"
:columns="leftFixedColumns" :columns="leftFixedColumns"
:column-rows="columnRows"
:obj-data="objData" :obj-data="objData"
:columns-width="columnsWidth" :columns-width="columnsWidth"
:data="rebuildData"></table-head> :data="rebuildData"></table-head>
@ -65,6 +67,7 @@
:prefix-cls="prefixCls" :prefix-cls="prefixCls"
:styleObject="fixedRightTableStyle" :styleObject="fixedRightTableStyle"
:columns="rightFixedColumns" :columns="rightFixedColumns"
:column-rows="columnRows"
:obj-data="objData" :obj-data="objData"
:columns-width="columnsWidth" :columns-width="columnsWidth"
:data="rebuildData"></table-head> :data="rebuildData"></table-head>
@ -97,6 +100,7 @@
import ExportCsv from './export-csv'; import ExportCsv from './export-csv';
import Locale from '../../mixins/locale'; import Locale from '../../mixins/locale';
import elementResizeDetectorMaker from 'element-resize-detector'; import elementResizeDetectorMaker from 'element-resize-detector';
import { getAllColumns, convertToRows, convertColumnOrder } from './util';
const prefixCls = 'ivu-table'; const prefixCls = 'ivu-table';
@ -180,6 +184,8 @@
objData: this.makeObjData(), // checkbox or highlight-row objData: this.makeObjData(), // checkbox or highlight-row
rebuildData: [], // for sort or filter rebuildData: [], // for sort or filter
cloneColumns: this.makeColumns(), cloneColumns: this.makeColumns(),
columnRows: this.makeColumnRows(),
allColumns: getAllColumns(this.columns), // for multiple table-head, get columns that have no children
showSlotHeader: true, showSlotHeader: true,
showSlotFooter: true, showSlotFooter: true,
bodyHeight: 0, bodyHeight: 0,
@ -308,28 +314,10 @@
return style; return style;
}, },
leftFixedColumns () { leftFixedColumns () {
let left = []; return convertColumnOrder(this.cloneColumns, 'left');
let other = [];
this.cloneColumns.forEach((col) => {
if (col.fixed && col.fixed === 'left') {
left.push(col);
} else {
//other.push(col);
}
});
return left.concat(other);
}, },
rightFixedColumns () { rightFixedColumns () {
let right = []; return convertColumnOrder(this.cloneColumns, 'right');
let other = [];
this.cloneColumns.forEach((col) => {
if (col.fixed && col.fixed === 'right') {
right.push(col);
} else {
//other.push(col);
}
});
return right.concat(other);
}, },
isLeftFixed () { isLeftFixed () {
return this.columns.some(col => col.fixed && col.fixed === 'left'); return this.columns.some(col => col.fixed && col.fixed === 'left');
@ -344,9 +332,9 @@
}, },
handleResize () { handleResize () {
this.$nextTick(() => { this.$nextTick(() => {
const allWidth = !this.columns.some(cell => !cell.width); // each column set a width const allWidth = !this.allColumns.some(cell => !cell.width); // each column set a width
if (allWidth) { if (allWidth) {
this.tableWidth = this.columns.map(cell => cell.width).reduce((a, b) => a + b, 0); this.tableWidth = this.allColumns.map(cell => cell.width).reduce((a, b) => a + b, 0);
} else { } else {
this.tableWidth = parseInt(getStyle(this.$el, 'width')) - 1; this.tableWidth = parseInt(getStyle(this.$el, 'width')) - 1;
} }
@ -614,7 +602,7 @@
this.cloneColumns[index]._sortType = type; this.cloneColumns[index]._sortType = type;
this.$emit('on-sort-change', { this.$emit('on-sort-change', {
column: JSON.parse(JSON.stringify(this.columns[this.cloneColumns[index]._index])), column: JSON.parse(JSON.stringify(this.allColumns[this.cloneColumns[index]._index])),
key: key, key: key,
order: type order: type
}); });
@ -751,7 +739,8 @@
return data; return data;
}, },
makeColumns () { makeColumns () {
let columns = deepCopy(this.columns); // data this.allColumns undefined
let columns = deepCopy(getAllColumns(this.columns));
let left = []; let left = [];
let right = []; let right = [];
let center = []; let center = [];
@ -789,6 +778,10 @@
}); });
return left.concat(center).concat(right); return left.concat(center).concat(right);
}, },
// create a multiple table-head
makeColumnRows () {
return convertToRows(this.columns);
},
exportCsv (params) { exportCsv (params) {
if (params.filename) { if (params.filename) {
if (params.filename.indexOf('.csv') === -1) { if (params.filename.indexOf('.csv') === -1) {
@ -804,7 +797,7 @@
columns = params.columns; columns = params.columns;
datas = params.data; datas = params.data;
} else { } else {
columns = this.columns; columns = this.allColumns;
if (!('original' in params)) params.original = true; if (!('original' in params)) params.original = true;
datas = params.original ? this.data : this.rebuildData; datas = params.original ? this.data : this.rebuildData;
} }
@ -863,7 +856,9 @@
columns: { columns: {
handler () { handler () {
// todo // todo
this.allColumns = getAllColumns(this.columns);
this.cloneColumns = this.makeColumns(); this.cloneColumns = this.makeColumns();
this.columnRows = this.makeColumnRows();
this.rebuildData = this.makeDataWithSortAndFilter(); this.rebuildData = this.makeDataWithSortAndFilter();
this.handleResize(); this.handleResize();
}, },

View file

@ -0,0 +1,81 @@
import { deepCopy } from '../../utils/assist';
// set forTableHead to true when convertToRows, false in normal cases like table.vue
const getAllColumns = (cols, forTableHead = false) => {
const columns = deepCopy(cols);
const result = [];
columns.forEach((column) => {
if (column.children) {
if (forTableHead) result.push(column);
result.push.apply(result, getAllColumns(column.children, forTableHead));
} else {
result.push(column);
}
});
return result;
};
export {getAllColumns};
const convertToRows = (columns) => {
const originColumns = deepCopy(columns);
let maxLevel = 1;
const traverse = (column, parent) => {
if (parent) {
column.level = parent.level + 1;
if (maxLevel < column.level) {
maxLevel = column.level;
}
}
if (column.children) {
let colSpan = 0;
column.children.forEach((subColumn) => {
traverse(subColumn, column);
colSpan += subColumn.colSpan;
});
column.colSpan = colSpan;
} else {
column.colSpan = 1;
}
};
originColumns.forEach((column) => {
column.level = 1;
traverse(column);
});
const rows = [];
for (let i = 0; i < maxLevel; i++) {
rows.push([]);
}
const allColumns = getAllColumns(originColumns, true);
allColumns.forEach((column) => {
if (!column.children) {
column.rowSpan = maxLevel - column.level + 1;
} else {
column.rowSpan = 1;
}
rows[column.level - 1].push(column);
});
return rows;
};
export {convertToRows};
const convertColumnOrder = (columns, FixedType) => {
let list = [];
let other = [];
columns.forEach((col) => {
if (col.fixed && col.fixed === FixedType) {
list.push(col);
} else {
other.push(col);
}
});
return list.concat(other);
};
export {convertColumnOrder};

View file

@ -71,7 +71,7 @@
overflow: hidden; overflow: hidden;
} }
&-body{ &-body{
//overflow: auto; overflow: auto;
//position: relative; //position: relative;
} }
@ -285,7 +285,7 @@
box-shadow: -2px 0 6px -2px rgba(0, 0, 0, 0.2); box-shadow: -2px 0 6px -2px rgba(0, 0, 0, 0.2);
} }
&-fixed-header{ &-fixed-header{
overflow: visible; overflow: hidden;
&-with-empty{ &-with-empty{
.@{table-prefix-cls}-hidden{ .@{table-prefix-cls}-hidden{
.@{table-prefix-cls}-sort{ .@{table-prefix-cls}-sort{