Cell Templates (Vue)

Wijmo interops for popular frameworks allow you to define custom content for grid cells declaratively, by using the frameworks' own template markup.

Such templates may include arbitrary components and HTML elements, with property and event bindings. All types of grid cells can be defined using templates (data cells, header cells, editors, etc).

This sample shows a grid with the templates for all cell types. The templates can be dynamically enabled or disabled by toggling the checkboxes.

This example uses Vue.

<template> <div class="container-fluid"> <p> Use a <b>wj-flex-grid-cell-template</b> element to define a cell template. The content of the <b>wj-flex-grid-cell-template</b> element defines the cell content. The <b>cellType</b> property specifies the type of the cells represented by the template. Use a <b>v-slot</b> directive to define a variable that contains an object with cell specific data, including the data item (<b>item</b>), row (<b>row</b>) and column (<b>col</b>) that the cell represents. </p> <p> Note that column-specific templates should be defined as children of the corresponding <b>wj-flex-grid-column</b> component, while the others are defined under the <b>wj-flex-grid</b> element. </p> <wj-flex-grid :itemsSource="itemsSource" :allowSorting="false" autoSizeMode="Both" allowResizing="Both" :deferResizing="true" :initialized="initialized"> <wj-flex-grid-cell-template cellType="TopLeft" v-if="customTopLeft"> № </wj-flex-grid-cell-template> <wj-flex-grid-cell-template cellType="BottomLeft" v-if="customBottomLeft"> &#931; </wj-flex-grid-cell-template> <wj-flex-grid-cell-template cellType="RowHeader" v-if="customRowHeader" v-slot="cell"> {{cell.row.index + 1}} </wj-flex-grid-cell-template> <wj-flex-grid-cell-template cellType="RowHeaderEdit" v-if="customRowHeaderEdit"> ... </wj-flex-grid-cell-template> <wj-flex-grid-column header="Country" binding="country" width="*"> <wj-flex-grid-cell-template cellType="Cell" v-if="customCell" v-slot="cell"> <img :src="'resources/' + cell.item.country + '.png'" /> {{cell.item.country}} </wj-flex-grid-cell-template> <wj-flex-grid-cell-template cellType="CellEdit" v-if="customCellEdit" v-slot="cell"> <wj-combo-box :itemsSource="countries" class="cell-editor" :selectedValue.sync="cell.value" :isEditable="false"> </wj-combo-box> </wj-flex-grid-cell-template> <wj-flex-grid-cell-template cellType="GroupHeader" v-if="customGroupHeader" v-slot="cell"> <input type="checkbox" v-model="cell.row.isCollapsed" /> {{cell.item.name}} ({{cell.item.items.length}} items) </wj-flex-grid-cell-template> </wj-flex-grid-column> <wj-flex-grid-column header="Downloads" binding="downloads" :width="170" aggregate="Sum"> <wj-flex-grid-cell-template cellType="ColumnHeader" v-if="customColumnHeader"> <input type="checkbox" v-model="highlightDownloads" /> Downloads </wj-flex-grid-cell-template> <wj-flex-grid-cell-template cellType="Cell" v-if="customCell" v-slot="cell"> <span :style="{color: highlightDownloads? (cell.item.downloads>10000 ?'green':'red'):''}" style="font-weight:700"> {{cell.item.downloads}} </span> </wj-flex-grid-cell-template> <wj-flex-grid-cell-template cellType="CellEdit" v-if="customCellEdit" v-slot="cell"> <wj-input-number class="cell-editor" v-model="cell.value" :step="1"></wj-input-number> </wj-flex-grid-cell-template> <wj-flex-grid-cell-template cellType="Group" v-if="customGroup" v-slot="cell"> Sum = {{formatNumber(cell.value, 'N0')}} </wj-flex-grid-cell-template> <wj-flex-grid-cell-template cellType="ColumnFooter" v-if="customColumnFooter" v-slot="cell"> Sum = {{formatNumber(cell.value, 'N0')}} </wj-flex-grid-cell-template> </wj-flex-grid-column> </wj-flex-grid> <div class="checkbox-list"> <div class="checkbox-list-title">Column level templates:</div> <div class="checkbox-cell"> <label class="checkbox"> <input type="checkbox" v-model="customCell" /> Cell </label> <label class="checkbox"> <input type="checkbox" v-model="customCellEdit" /> CellEdit </label> </div> <div class="checkbox-cell"> <label class="checkbox"> <input type="checkbox" v-model="customColumnHeader" /> ColumnHeader </label> <label class="checkbox"> <input type="checkbox" v-model="customColumnFooter" /> ColumnFooter </label> </div> <div class="checkbox-cell"> <label class="checkbox"> <input type="checkbox" v-model="customGroupHeader" /> GroupHeader </label> <label class="checkbox"> <input type="checkbox" v-model="customGroup" /> Group </label> </div> <div class="checkbox-list-title">Grid level templates:</div> <div class="checkbox-cell"> <label class="checkbox"> <input type="checkbox" v-model="customTopLeft" /> TopLeft </label> <label class="checkbox"> <input type="checkbox" v-model="customBottomLeft" /> BottomLeft </label> </div> <div class="checkbox-cell"> <label class="checkbox"> <input type="checkbox" v-model="customRowHeader" /> RowHeader </label> <label class="checkbox"> <input type="checkbox" v-model="customRowHeaderEdit" /> RowHeaderEdit </label> </div> </div> </div> </template> <script> import "@grapecity/wijmo.styles/wijmo.css"; import "bootstrap.css"; import Vue from "vue"; import * as wjcCore from "@grapecity/wijmo"; import * as wjcGrid from "@grapecity/wijmo.grid"; import "@grapecity/wijmo.vue2.input"; import "@grapecity/wijmo.vue2.grid"; import * as dataService from './data'; let App = Vue.extend({ name: "app", data: function () { return { itemsSource: dataService.getCv(dataService.getData()), countries: dataService.getCountries(), customTopLeft: true, customBottomLeft: true, customRowHeader: true, customRowHeaderEdit: true, customCell: true, customCellEdit: true, customGroupHeader: true, customColumnHeader: true, customGroup: true, customColumnFooter: true, highlightDownloads: true } }, methods: { initialized: function(grid, e) { grid.columnFooters.rows.push(new wjcGrid.GroupRow()); }, formatNumber: function(value, format) { return wjcCore.Globalize.formatNumber(value, format); } }, }); new Vue({ render: h => h(App) }).$mount("#app"); </script> <style> body { margin-bottom: 24px; } label { margin-right: 3px; } .checkbox-list { padding: 0 20px; } .checkbox-cell { display: table-cell; padding-right: 50px; } .checkbox-list .checkbox { margin: 10px 0 0 0; } .checkbox-list-title { font-size: 18px; margin: 10px 0px 2px -20px; } .wj-flexgrid { max-height: 350px; max-width: 600px; margin: 10px 0; } .wj-cell .cell-editor { position: absolute; left: 0px; width: 100%; border-radius: 0px; margin: -4px 0 -3px 0; } </style>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Cell Templates</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app.vue'); </script> </head> <body> <div id="app"> </div> </body> </html>
import { CollectionView } from '@grapecity/wijmo'; export function getData() { var countries = getCountries(), data = []; for (var i = 0; i < 30; i++) { data.push({ id: i, date: new Date(2015, Math.floor(i / countries.length) % 12, (Math.floor(i / countries.length) + 1) % 28), country: countries[i % countries.length], countryMapped: i % countries.length, downloads: Math.round(Math.random() * 20000), sales: Math.random() * 10000, expenses: Math.random() * 5000, checked: i % 9 == 0 }); } return data; } export function getCountries() { return 'US,Germany,UK,Japan,Italy,Greece'.split(','); } export function getCv() { return new CollectionView(getData(), { sortDescriptions: ['date'], groupDescriptions: ['country'] }); }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, meta: { '*.css': { loader: 'css' }, '*.vue': { loader: 'vue-loader' } //'*.vue': { loader: 'systemjs-plugin-vue' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@grapecity/wijmo': 'npm:@grapecity/wijmo/index.js', '@grapecity/wijmo.input': 'npm:@grapecity/wijmo.input/index.js', '@grapecity/wijmo.styles': 'npm:@grapecity/wijmo.styles', '@grapecity/wijmo.cultures': 'npm:@grapecity/wijmo.cultures', '@grapecity/wijmo.chart': 'npm:@grapecity/wijmo.chart/index.js', '@grapecity/wijmo.chart.analytics': 'npm:@grapecity/wijmo.chart.analytics/index.js', '@grapecity/wijmo.chart.animation': 'npm:@grapecity/wijmo.chart.animation/index.js', '@grapecity/wijmo.chart.annotation': 'npm:@grapecity/wijmo.chart.annotation/index.js', '@grapecity/wijmo.chart.finance': 'npm:@grapecity/wijmo.chart.finance/index.js', '@grapecity/wijmo.chart.finance.analytics': 'npm:@grapecity/wijmo.chart.finance.analytics/index.js', '@grapecity/wijmo.chart.hierarchical': 'npm:@grapecity/wijmo.chart.hierarchical/index.js', '@grapecity/wijmo.chart.interaction': 'npm:@grapecity/wijmo.chart.interaction/index.js', '@grapecity/wijmo.chart.radar': 'npm:@grapecity/wijmo.chart.radar/index.js', '@grapecity/wijmo.chart.render': 'npm:@grapecity/wijmo.chart.render/index.js', '@grapecity/wijmo.chart.webgl': 'npm:@grapecity/wijmo.chart.webgl/index.js', '@grapecity/wijmo.gauge': 'npm:@grapecity/wijmo.gauge/index.js', '@grapecity/wijmo.grid': 'npm:@grapecity/wijmo.grid/index.js', '@grapecity/wijmo.grid.detail': 'npm:@grapecity/wijmo.grid.detail/index.js', '@grapecity/wijmo.grid.filter': 'npm:@grapecity/wijmo.grid.filter/index.js', '@grapecity/wijmo.grid.search': 'npm:@grapecity/wijmo.grid.search/index.js', '@grapecity/wijmo.grid.grouppanel': 'npm:@grapecity/wijmo.grid.grouppanel/index.js', '@grapecity/wijmo.grid.multirow': 'npm:@grapecity/wijmo.grid.multirow/index.js', '@grapecity/wijmo.grid.transposed': 'npm:@grapecity/wijmo.grid.transposed/index.js', '@grapecity/wijmo.grid.pdf': 'npm:@grapecity/wijmo.grid.pdf/index.js', '@grapecity/wijmo.grid.sheet': 'npm:@grapecity/wijmo.grid.sheet/index.js', '@grapecity/wijmo.grid.xlsx': 'npm:@grapecity/wijmo.grid.xlsx/index.js', '@grapecity/wijmo.grid.selector': 'npm:@grapecity/wijmo.grid.selector/index.js', '@grapecity/wijmo.grid.cellmaker': 'npm:@grapecity/wijmo.grid.cellmaker/index.js', '@grapecity/wijmo.nav': 'npm:@grapecity/wijmo.nav/index.js', '@grapecity/wijmo.odata': 'npm:@grapecity/wijmo.odata/index.js', '@grapecity/wijmo.olap': 'npm:@grapecity/wijmo.olap/index.js', '@grapecity/wijmo.pdf': 'npm:@grapecity/wijmo.pdf/index.js', '@grapecity/wijmo.viewer': 'npm:@grapecity/wijmo.viewer/index.js', '@grapecity/wijmo.xlsx': 'npm:@grapecity/wijmo.xlsx/index.js', '@grapecity/wijmo.undo': 'npm:@grapecity/wijmo.undo/index.js', '@grapecity/wijmo.interop.grid': 'npm:@grapecity/wijmo.interop.grid/index.js', '@grapecity/wijmo.touch': 'npm:@grapecity/wijmo.touch/index.js', '@grapecity/wijmo.cloud': 'npm:@grapecity/wijmo.cloud/index.js', "@grapecity/wijmo.vue2.chart.analytics": "npm:@grapecity/wijmo.vue2.chart.analytics/index.js", "@grapecity/wijmo.vue2.chart.animation": "npm:@grapecity/wijmo.vue2.chart.animation/index.js", "@grapecity/wijmo.vue2.chart.annotation": "npm:@grapecity/wijmo.vue2.chart.annotation/index.js", "@grapecity/wijmo.vue2.chart.finance.analytics": "npm:@grapecity/wijmo.vue2.chart.finance.analytics/index.js", "@grapecity/wijmo.vue2.chart.finance": "npm:@grapecity/wijmo.vue2.chart.finance/index.js", "@grapecity/wijmo.vue2.chart.hierarchical": "npm:@grapecity/wijmo.vue2.chart.hierarchical/index.js", "@grapecity/wijmo.vue2.chart.interaction": "npm:@grapecity/wijmo.vue2.chart.interaction/index.js", "@grapecity/wijmo.vue2.chart.radar": "npm:@grapecity/wijmo.vue2.chart.radar/index.js", "@grapecity/wijmo.vue2.chart": "npm:@grapecity/wijmo.vue2.chart/index.js", "@grapecity/wijmo.vue2.core": "npm:@grapecity/wijmo.vue2.core/index.js", "@grapecity/wijmo.vue2.gauge": "npm:@grapecity/wijmo.vue2.gauge/index.js", "@grapecity/wijmo.vue2.grid.detail": "npm:@grapecity/wijmo.vue2.grid.detail/index.js", "@grapecity/wijmo.vue2.grid.filter": "npm:@grapecity/wijmo.vue2.grid.filter/index.js", "@grapecity/wijmo.vue2.grid.grouppanel": "npm:@grapecity/wijmo.vue2.grid.grouppanel/index.js", '@grapecity/wijmo.vue2.grid.search': 'npm:@grapecity/wijmo.vue2.grid.search/index.js', "@grapecity/wijmo.vue2.grid.multirow": "npm:@grapecity/wijmo.vue2.grid.multirow/index.js", "@grapecity/wijmo.vue2.grid.sheet": "npm:@grapecity/wijmo.vue2.grid.sheet/index.js", '@grapecity/wijmo.vue2.grid.transposed': 'npm:@grapecity/wijmo.vue2.grid.transposed/index.js', "@grapecity/wijmo.vue2.grid": "npm:@grapecity/wijmo.vue2.grid/index.js", "@grapecity/wijmo.vue2.input": "npm:@grapecity/wijmo.vue2.input/index.js", "@grapecity/wijmo.vue2.olap": "npm:@grapecity/wijmo.vue2.olap/index.js", "@grapecity/wijmo.vue2.viewer": "npm:@grapecity/wijmo.vue2.viewer/index.js", "@grapecity/wijmo.vue2.nav": "npm:@grapecity/wijmo.vue2.nav/index.js", "@grapecity/wijmo.vue2.base": "npm:@grapecity/wijmo.vue2.base/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.min.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);