Column Groups (Vue)

This sample shows how you can create column groups by initializing the grid's columnGroups collection with an array of hierarchical elements where columns may have a columns property containing child columns.

The column groups may be collapsible and configured to show any of the child columns when the group is collapsed.

You can use CSS to animate the column groups as they expand or collapse.

Learn about FlexGrid | FlexGrid API Reference

This example uses Vue.

The demo is being dynamically compiled to support real-time code editing... For quicker access to features, switch to the "JavaScript" tab for a smoother experience! :)
app.vue
index.html
data.js
Copy to CodeMine
loading...
<template> <main class="app container-fluid"> <label> Collapse/Expand Animation <input type="checkbox" v-model="animated" /> </label> <button id="toggle" class="btn btn-primary" @click="toggleGroups"> Toggle Column Groups </button> <div v-bind:class="{ animated: animated }"> <wj-flex-grid headersVisibility="Column" showSelectedHeaders="All" :alternatingRowStep="0" :showMarquee="true" :autoGenerateColumns="false" :columnGroups="columnGroups" :itemsSource="data" /> </div> </main> </template> <script setup> import "https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/css/flag-icon.css"; import * as DataService from "./data"; import { ref } from "vue"; const data = ref(DataService.getData()); const animated = ref(true); const colGroups1 = DataService.getColumnGroups() const colGroups2 = DataService.getDeeperColumnGroups() const columnGroups = ref(colGroups1); const toggle = ref(false); function toggleGroups() { toggle.value = !toggle.value; columnGroups.value = toggle.value ? colGroups2 : colGroups1; } </script> <style> .app label { display: block; } .wj-flexgrid { margin: 10px 0; } /* highlight the main column in the group */ .wj-flexgrid .wj-cells .wj-cell.main-column { background: #e3f4ff; } /* some conditional formatting */ .big-val { font-weight: bold; color: darkgreen; } .small-val { font-style: italic; color: rgb(202, 0, 0); } /* some animation when collapsing/expanding the groups */ .animated .wj-flexgrid .wj-colheaders .wj-header.wj-cell.wj-colgroup { transition: all .2s; } </style>
<template> <main class="app container-fluid"> <label> Collapse/Expand Animation <input type="checkbox" v-model="animated" /> </label> <button id="toggle" class="btn btn-primary" @click="toggleGroups"> Toggle Column Groups </button> <div v-bind:class="{ animated: animated }"> <wj-flex-grid headersVisibility="Column" showSelectedHeaders="All" :alternatingRowStep="0" :showMarquee="true" :autoGenerateColumns="false" :columnGroups="columnGroups" :itemsSource="data" /> </div> </main> </template> <script setup> import "https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.1.0/css/flag-icon.css"; import * as DataService from "./data"; import { ref } from "vue"; const data = ref(DataService.getData()); const animated = ref(true); const colGroups1 = DataService.getColumnGroups() const colGroups2 = DataService.getDeeperColumnGroups() const columnGroups = ref(colGroups1); const toggle = ref(false); function toggleGroups() { toggle.value = !toggle.value; columnGroups.value = toggle.value ? colGroups2 : colGroups1; } </script> <style> .app label { display: block; } .wj-flexgrid { margin: 10px 0; } /* highlight the main column in the group */ .wj-flexgrid .wj-cells .wj-cell.main-column { background: #e3f4ff; } /* some conditional formatting */ .big-val { font-weight: bold; color: darkgreen; } .small-val { font-style: italic; color: rgb(202, 0, 0); } /* some animation when collapsing/expanding the groups */ .animated .wj-flexgrid .wj-colheaders .wj-header.wj-cell.wj-colgroup { transition: all .2s; } </style>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>MESCIUS Wijmo FlexGrid Column Groups</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="compiler.js" type="module"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.21.5/system.src.js" integrity="sha512-skZbMyvYdNoZfLmiGn5ii6KmklM82rYX2uWctBhzaXPxJgiv4XBwJnFGr5k8s+6tE1pcR1nuTKghozJHyzMcoA==" crossorigin="anonymous"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app.js'); </script> </head> <body> <div id="app"> </div> </body> </html>
// get an array with hierarchical column definitions // the 'columns' property of the objects contain child columns // the 'collapseTo' property specifies the binding of thei child column that // should remain visible when the group is collapsed. export function getColumnGroups() { const allocTemplate = (ctx)=>(`<span class=${ctx.value > .2 ? "big-val" : "small-val"}> ${wijmo.Globalize.format(ctx.value, ctx.col.format)} </span>`); const amountTemplate = (ctx)=>(`<span class=${ctx.value > 50000 ? "big-val" : "small-val"}> ${wijmo.Globalize.format(ctx.value, ctx.col.format) }</span>`); return [ { binding: 'name', header: 'Name', width: 150 }, { binding: 'currency', header: 'Curr', width: 80, align: 'center' }, { header: 'Perf', align: 'center', collapseTo: 'perf.ytd', columns: [ { binding: 'perf.ytd', header: 'YTD', format: 'p2', width: 100, cssClass: 'main-column' }, { binding: 'perf.m1', header: '1 M', format: 'p2', width: 80 }, { binding: 'perf.m6', header: '6 M', format: 'p2', width: 80 }, { binding: 'perf.m12', header: '12 M', format: 'p2', width: 80 }, ] }, { header: 'Allocation', align: 'center', collapseTo: 'alloc.amount', columns: [ { binding: 'alloc.stock', header: 'Stocks', format: 'p0', width: 80, cellTemplate: allocTemplate }, { binding: 'alloc.bond', header: 'Bonds', format: 'p0', width: 80, cellTemplate: allocTemplate }, { binding: 'alloc.cash', header: 'Cash', format: 'p0', width: 80, cellTemplate: allocTemplate }, { binding: 'alloc.other', header: 'Other', format: 'p0', width: 80, cellTemplate: allocTemplate }, { binding: 'alloc.amount', header: 'Amount', format: 'c0', width: 100, cssClass: 'main-column', cellTemplate: amountTemplate } ] } ]; } // slightly different column groups export function getDeeperColumnGroups() { return [ { binding: 'name', header: 'Name', width: 150 }, { binding: 'currency', header: 'Curr', width: 80, align: 'center' }, { header: 'Allocation', align: 'center', collapseTo: 'alloc.amount', columns: [ { binding: 'alloc.stock', header: 'Stocks', format: 'p0', width: 80 }, { binding: 'alloc.bond', header: 'Bonds', format: 'p0', width: 80 }, { header: 'Detail', align: 'center', columns: [ { binding: 'alloc.cash', header: 'Cash', format: 'p0', width: 80 }, { binding: 'alloc.other', header: 'Other', format: 'p0', width: 80 }, ] }, { binding: 'alloc.amount', header: 'Amount', format: 'c0', width: 100, cssClassAll: 'main-column' }, ] }, { header: 'Perf', align: 'center', columns: [ { header: 'Short', align: 'center', collapseTo: 'perf.ytd', isCollapsed: true, columns: [ { binding: 'perf.ytd', header: 'YTD', format: 'p2', width: 100, cssClassAll: 'main-column' }, { binding: 'perf.m1', header: '1 M', format: 'p2', width: 80 }, ] }, { header: 'Long', align: 'center', collapseTo: 'perf.m12', isCollapsed: true, columns: [ { binding: 'perf.m6', header: '6 M', format: 'p2', width: 80 }, { binding: 'perf.m12', header: '12 M', format: 'p2', width: 100, cssClassAll: 'main-column' } ] }, ] }, ]; } // get some sample data export function getData() { return [{ name: 'Constant Growth', currency: 'USD', perf: { ytd: .0523, m1: 0.0142, m6: 0.0443, m12: 0.0743 }, alloc: { stock: 0.17, bond: 0.32, cash: 0.36, other: 0.15, amount: 23432 } }, { name: 'Optimus Prime', currency: 'EUR', perf: { ytd: .0343, m1: 0.043, m6: 0.0244, m12: 0.0543 }, alloc: { stock: 0.61, bond: 0.8, cash: 0.9, other: 0.22, amount: 43223 } }, { name: 'Crypto Planet', currency: 'BTC', perf: { ytd: .0343, m1: 0.014, m6: 0.034, m12: 0.01243 }, alloc: { stock: 0.1, bond: 0, cash: 0, other: 0.9, amount: 2234 } }, { name: 'MegaZone', currency: 'EUR', perf: { ytd: .0443, m1: 0.034, m6: 0.0424, m12: 0.0343 }, alloc: { stock: 0.51, bond: 0.9, cash: 0.8, other: 0.12, amount: 32234 } }, { name: 'Serenity', currency: 'YEN', perf: { ytd: .0522, m1: 0.0143, m6: 0.0458, m12: 0.0732 }, alloc: { stock: 0.66, bond: 0.09, cash: 0.19, other: 0.06, amount: 65624 } }]; }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, meta: { '*.css': { loader: 'css' }, '*.vue': { loader: '../plugin-vue/index.js' } //'*.vue': { loader: 'systemjs-plugin-vue' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@mescius/wijmo': 'npm:@mescius/wijmo/index.js', '@mescius/wijmo.input': 'npm:@mescius/wijmo.input/index.js', '@mescius/wijmo.styles': 'npm:@mescius/wijmo.styles', '@mescius/wijmo.cultures': 'npm:@mescius/wijmo.cultures', '@mescius/wijmo.chart': 'npm:@mescius/wijmo.chart/index.js', '@mescius/wijmo.chart.analytics': 'npm:@mescius/wijmo.chart.analytics/index.js', '@mescius/wijmo.chart.animation': 'npm:@mescius/wijmo.chart.animation/index.js', '@mescius/wijmo.chart.annotation': 'npm:@mescius/wijmo.chart.annotation/index.js', '@mescius/wijmo.chart.finance': 'npm:@mescius/wijmo.chart.finance/index.js', '@mescius/wijmo.chart.finance.analytics': 'npm:@mescius/wijmo.chart.finance.analytics/index.js', '@mescius/wijmo.chart.hierarchical': 'npm:@mescius/wijmo.chart.hierarchical/index.js', '@mescius/wijmo.chart.interaction': 'npm:@mescius/wijmo.chart.interaction/index.js', '@mescius/wijmo.chart.radar': 'npm:@mescius/wijmo.chart.radar/index.js', '@mescius/wijmo.chart.render': 'npm:@mescius/wijmo.chart.render/index.js', '@mescius/wijmo.chart.webgl': 'npm:@mescius/wijmo.chart.webgl/index.js', '@mescius/wijmo.chart.map': 'npm:@mescius/wijmo.chart.map/index.js', '@mescius/wijmo.gauge': 'npm:@mescius/wijmo.gauge/index.js', '@mescius/wijmo.grid': 'npm:@mescius/wijmo.grid/index.js', '@mescius/wijmo.grid.detail': 'npm:@mescius/wijmo.grid.detail/index.js', '@mescius/wijmo.grid.filter': 'npm:@mescius/wijmo.grid.filter/index.js', '@mescius/wijmo.grid.search': 'npm:@mescius/wijmo.grid.search/index.js', '@mescius/wijmo.grid.style': 'npm:@mescius/wijmo.grid.style/index.js', '@mescius/wijmo.grid.grouppanel': 'npm:@mescius/wijmo.grid.grouppanel/index.js', '@mescius/wijmo.grid.multirow': 'npm:@mescius/wijmo.grid.multirow/index.js', '@mescius/wijmo.grid.transposed': 'npm:@mescius/wijmo.grid.transposed/index.js', '@mescius/wijmo.grid.transposedmultirow': 'npm:@mescius/wijmo.grid.transposedmultirow/index.js', '@mescius/wijmo.grid.pdf': 'npm:@mescius/wijmo.grid.pdf/index.js', '@mescius/wijmo.grid.sheet': 'npm:@mescius/wijmo.grid.sheet/index.js', '@mescius/wijmo.grid.xlsx': 'npm:@mescius/wijmo.grid.xlsx/index.js', '@mescius/wijmo.grid.selector': 'npm:@mescius/wijmo.grid.selector/index.js', '@mescius/wijmo.grid.cellmaker': 'npm:@mescius/wijmo.grid.cellmaker/index.js', '@mescius/wijmo.nav': 'npm:@mescius/wijmo.nav/index.js', '@mescius/wijmo.odata': 'npm:@mescius/wijmo.odata/index.js', '@mescius/wijmo.olap': 'npm:@mescius/wijmo.olap/index.js', '@mescius/wijmo.rest': 'npm:@mescius/wijmo.rest/index.js', '@mescius/wijmo.pdf': 'npm:@mescius/wijmo.pdf/index.js', '@mescius/wijmo.pdf.security': 'npm:@mescius/wijmo.pdf.security/index.js', '@mescius/wijmo.viewer': 'npm:@mescius/wijmo.viewer/index.js', '@mescius/wijmo.xlsx': 'npm:@mescius/wijmo.xlsx/index.js', '@mescius/wijmo.undo': 'npm:@mescius/wijmo.undo/index.js', '@mescius/wijmo.interop.grid': 'npm:@mescius/wijmo.interop.grid/index.js', '@mescius/wijmo.touch': 'npm:@mescius/wijmo.touch/index.js', '@mescius/wijmo.cloud': 'npm:@mescius/wijmo.cloud/index.js', '@mescius/wijmo.barcode': 'npm:@mescius/wijmo.barcode/index.js', '@mescius/wijmo.barcode.common': 'npm:@mescius/wijmo.barcode.common/index.js', '@mescius/wijmo.barcode.composite': 'npm:@mescius/wijmo.barcode.composite/index.js', '@mescius/wijmo.barcode.specialized': 'npm:@mescius/wijmo.barcode.specialized/index.js', "@mescius/wijmo.vue2.chart.analytics": "npm:@mescius/wijmo.vue2.chart.analytics/index.js", "@mescius/wijmo.vue2.chart.animation": "npm:@mescius/wijmo.vue2.chart.animation/index.js", "@mescius/wijmo.vue2.chart.annotation": "npm:@mescius/wijmo.vue2.chart.annotation/index.js", "@mescius/wijmo.vue2.chart.finance.analytics": "npm:@mescius/wijmo.vue2.chart.finance.analytics/index.js", "@mescius/wijmo.vue2.chart.finance": "npm:@mescius/wijmo.vue2.chart.finance/index.js", "@mescius/wijmo.vue2.chart.hierarchical": "npm:@mescius/wijmo.vue2.chart.hierarchical/index.js", "@mescius/wijmo.vue2.chart.interaction": "npm:@mescius/wijmo.vue2.chart.interaction/index.js", "@mescius/wijmo.vue2.chart.radar": "npm:@mescius/wijmo.vue2.chart.radar/index.js", '@mescius/wijmo.vue2.chart.map': 'npm:@mescius/wijmo.vue2.chart.map/index.js', "@mescius/wijmo.vue2.chart": "npm:@mescius/wijmo.vue2.chart/index.js", "@mescius/wijmo.vue2.core": "npm:@mescius/wijmo.vue2.core/index.js", "@mescius/wijmo.vue2.gauge": "npm:@mescius/wijmo.vue2.gauge/index.js", "@mescius/wijmo.vue2.grid.detail": "npm:@mescius/wijmo.vue2.grid.detail/index.js", "@mescius/wijmo.vue2.grid.filter": "npm:@mescius/wijmo.vue2.grid.filter/index.js", "@mescius/wijmo.vue2.grid.grouppanel": "npm:@mescius/wijmo.vue2.grid.grouppanel/index.js", '@mescius/wijmo.vue2.grid.search': 'npm:@mescius/wijmo.vue2.grid.search/index.js', "@mescius/wijmo.vue2.grid.multirow": "npm:@mescius/wijmo.vue2.grid.multirow/index.js", "@mescius/wijmo.vue2.grid.sheet": "npm:@mescius/wijmo.vue2.grid.sheet/index.js", '@mescius/wijmo.vue2.grid.transposed': 'npm:@mescius/wijmo.vue2.grid.transposed/index.js', '@mescius/wijmo.vue2.grid.transposedmultirow': 'npm:@mescius/wijmo.vue2.grid.transposedmultirow/index.js', "@mescius/wijmo.vue2.grid": "npm:@mescius/wijmo.vue2.grid/index.js", "@mescius/wijmo.vue2.input": "npm:@mescius/wijmo.vue2.input/index.js", "@mescius/wijmo.vue2.olap": "npm:@mescius/wijmo.vue2.olap/index.js", "@mescius/wijmo.vue2.viewer": "npm:@mescius/wijmo.vue2.viewer/index.js", "@mescius/wijmo.vue2.nav": "npm:@mescius/wijmo.vue2.nav/index.js", "@mescius/wijmo.vue2.base": "npm:@mescius/wijmo.vue2.base/index.js", '@mescius/wijmo.vue2.barcode.common': 'npm:@mescius/wijmo.vue2.barcode.common/index.js', '@mescius/wijmo.vue2.barcode.composite': 'npm:@mescius/wijmo.vue2.barcode.composite/index.js', '@mescius/wijmo.vue2.barcode.specialized': 'npm:@mescius/wijmo.vue2.barcode.specialized/index.js', 'bootstrap.css': 'npm:bootstrap/dist/css/bootstrap.min.css', 'jszip': 'npm:jszip/dist/jszip.js', 'css': 'npm:systemjs-plugin-css/css.js', 'vue': 'npm:vue/dist/vue.cjs.js', '@vue/compiler-dom':'npm:@vue/compiler-dom/dist/compiler-dom.global.prod.js', '@vue/runtime-dom':'npm:@vue/runtime-dom/dist/runtime-dom.global.prod.js', '@vue/shared':'npm:@vue/shared/dist/shared.cjs.js', '@vue/compiler-dom':'npm:@vue/compiler-dom/dist/compiler-dom.global.prod.js', '@vue/runtime-dom':'npm:@vue/runtime-dom/dist/runtime-dom.global.prod.js', '@vue/shared':'npm:@vue/shared/dist/shared.cjs.js', '@vue/compiler-dom':'npm:@vue/compiler-dom/dist/compiler-dom.global.prod.js', '@vue/runtime-dom':'npm:@vue/runtime-dom/dist/runtime-dom.global.prod.js', '@vue/shared':'npm:@vue/shared/dist/shared.cjs.js', '@vue/compiler-dom':'npm:@vue/compiler-dom/dist/compiler-dom.global.prod.js', '@vue/runtime-dom':'npm:@vue/runtime-dom/dist/runtime-dom.global.prod.js', '@vue/shared':'npm:@vue/shared/dist/shared.cjs.js', '@vue/compiler-dom':'npm:@vue/compiler-dom/dist/compiler-dom.global.prod.js', '@vue/runtime-dom':'npm:@vue/runtime-dom/dist/runtime-dom.global.prod.js', '@vue/shared':'npm:@vue/shared/dist/shared.cjs.js', '@vue/compiler-dom':'npm:@vue/compiler-dom/dist/compiler-dom.global.prod.js', '@vue/runtime-dom':'npm:@vue/runtime-dom/dist/runtime-dom.global.prod.js', '@vue/shared':'npm:@vue/shared/dist/shared.cjs.js', '@vue/compiler-dom':'npm:@vue/compiler-dom/dist/compiler-dom.global.prod.js', '@vue/runtime-dom':'npm:@vue/runtime-dom/dist/runtime-dom.global.prod.js', '@vue/shared':'npm:@vue/shared/dist/shared.cjs.js', '@vue/compiler-dom':'npm:@vue/compiler-dom/dist/compiler-dom.global.prod.js', '@vue/runtime-dom':'npm:@vue/runtime-dom/dist/runtime-dom.global.prod.js', '@vue/shared':'npm:@vue/shared/dist/shared.cjs.js', 'vue-loader': 'npm:systemjs-vue-browser/index.js', //'systemjs-plugin-vue': 'npm:systemjs-plugin-vue/index.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build': 'npm:systemjs-plugin-babel/systemjs-babel-browser.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'js' }, rxjs: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' }, wijmo: { defaultExtension: 'js', } } }); })(this);