Row Groups (Vue)

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

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

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

Learn about FlexGrid | TransposedGrid API Reference

This example uses Vue.

app.vue
index.html
data.js
Copy to CodeMine
<template> <div class="container-fluid"> <label> Collapse/Expand Animation <input type="checkbox" v-model="animated" /> </label> <button id="toggle" class="btn btn-primary" @click="toggleGroups"> Toggle Row Groups </button> <div v-bind:class="{ animated: animated }"> <wj-transposed-grid showSelectedHeaders="Row" :alternatingRowStep="0" :showMarquee="true" :autoGenerateRows="false" :rowGroups="rowGroups" :itemsSource="data" /> </div> </div> </template> <script setup> import "@mescius/wijmo.touch"; import { getRowGroups, getDeeperRowGroups, getData } from "./data"; import { ref } from "vue"; const rowGroups1 = getRowGroups(); const rowGroups2 = getDeeperRowGroups(); const data = ref(getData()); const animated = ref(true); const rowGroups = ref(rowGroups1); const toggle = ref(false); function toggleGroups() { toggle.value = !toggle.value; rowGroups.value = toggle.value ? rowGroups2 : rowGroups1; } </script> <style> @import "./node_modules/bootstrap/dist/css/bootstrap.css"; @import "./node_modules/@mescius/wijmo.styles/wijmo.css"; label { display: block; } .wj-transposed-grid { margin: 10px 0; } /* highlight the main row in the group */ .wj-flexgrid .wj-cells .wj-cell.main-row:not(.wj-state-selected):not(.wj-state-multi-selected) { 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-rowheaders .wj-header.wj-cell.wj-colgroup { transition: all .2s; } </style>
<template> <div class="container-fluid"> <label> Collapse/Expand Animation <input type="checkbox" v-model="animated" /> </label> <button id="toggle" class="btn btn-primary" @click="toggleGroups"> Toggle Row Groups </button> <div v-bind:class="{ animated: animated }"> <wj-transposed-grid showSelectedHeaders="Row" :alternatingRowStep="0" :showMarquee="true" :autoGenerateRows="false" :rowGroups="rowGroups" :itemsSource="data" /> </div> </div> </template> <script setup> import "@mescius/wijmo.touch"; import { getRowGroups, getDeeperRowGroups, getData } from "./data"; import { ref } from "vue"; const rowGroups1 = getRowGroups(); const rowGroups2 = getDeeperRowGroups(); const data = ref(getData()); const animated = ref(true); const rowGroups = ref(rowGroups1); const toggle = ref(false); function toggleGroups() { toggle.value = !toggle.value; rowGroups.value = toggle.value ? rowGroups2 : rowGroups1; } </script> <style> @import "./node_modules/bootstrap/dist/css/bootstrap.css"; @import "./node_modules/@mescius/wijmo.styles/wijmo.css"; label { display: block; } .wj-transposed-grid { margin: 10px 0; } /* highlight the main row in the group */ .wj-flexgrid .wj-cells .wj-cell.main-row:not(.wj-state-selected):not(.wj-state-multi-selected) { 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-rowheaders .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 TransposedGrid Row 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 row definitions // the 'rows' property of the objects contain child rows // the 'collapseTo' property specifies the binding of their child row that // should remain visible when the group is collapsed. export function getRowGroups() { 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', height: 50 }, { binding: 'currency', header: 'Curr', height: 50, align: 'center' }, { header: 'Perf', width: 100, align: 'center', collapseTo: 'perf.ytd', rows: [ { binding: 'perf.ytd', header: 'YTD', format: 'p2', width: 80, cssClass: 'main-row' }, { binding: 'perf.m1', header: '1 M', format: 'p2', width: 60 }, { binding: 'perf.m6', header: '6 M', format: 'p2', width: 60 }, { binding: 'perf.m12', header: '12 M', format: 'p2', width: 60 }, ] }, { header: 'Allocation', width: 100, align: 'center', collapseTo: 'alloc.amount', rows: [ { 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: 80, cssClass: 'main-row', cellTemplate: amountTemplate } ] } ]; } export function getDeeperRowGroups() { return [ { binding: 'name', header: 'Name', height: 50 }, { binding: 'currency', header: 'Curr', height: 50, align: 'center' }, { header: 'Allocation', width: 100, align: 'center', collapseTo: 'alloc.amount', rows: [ { binding: 'alloc.stock', header: 'Stocks', format: 'p0' }, { binding: 'alloc.bond', header: 'Bonds', format: 'p0' }, { header: 'Detail', width: 80, align: 'center', rows: [ { binding: 'alloc.cash', header: 'Cash', format: 'p0', width: 60 }, { binding: 'alloc.other', header: 'Other', format: 'p0', width: 60 }, ] }, { binding: 'alloc.amount', header: 'Amount', format: 'c0', cssClassAll: 'main-row' }, ] }, { header: 'Perf', width: 100, align: 'center', rows: [ { header: 'Short', width: 80, align: 'center', collapseTo: 'perf.ytd', isCollapsed: true, rows: [ { binding: 'perf.ytd', header: 'YTD', format: 'p2', width: 60, cssClassAll: 'main-row' }, { binding: 'perf.m1', header: '1 M', format: 'p2', width: 60 }, ] }, { header: 'Long', width: 80, align: 'center', collapseTo: 'perf.m12', isCollapsed: true, rows: [ { binding: 'perf.m6', header: '6 M', format: 'p2', width: 60 }, { binding: 'perf.m12', header: '12 M', format: 'p2', width: 60, cssClassAll: 'main-row' } ] }, ] }, ]; } // 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);