Skip to content

Pivot Table Demo




Source code
src/components/showcase-pivot/PivotShowcase.ts
import { defineCustomElements } from '@revolist/revogrid/loader';
defineCustomElements();
import { PivotPlugin, AdvanceFilterPlugin, type PivotConfig } from '@revolist/revogrid-pro';
import { ECOMMERCE_COLUMNS, ECOMMERCE_COLUMNS_TYPES } from '../sys-data/ecommerce.columns';
import { ECOMMERCE_PIVOT } from '../sys-data/ecommerce.pivot';
import type { GroupingOptions, ColumnProp } from '@revolist/vue3-datagrid';
// ---------------------
// State Management
// ---------------------
let pivot: PivotConfig | null = { ...ECOMMERCE_PIVOT };
let newCfg = { ...ECOMMERCE_PIVOT };
let rowGroupingEnabled = false;
let pivotRowsGrouping: ColumnProp[] = []; // will be updated via pivot config events
function getRowGrouping(): GroupingOptions | undefined {
if (!rowGroupingEnabled || pivotRowsGrouping.length < 2) {
return undefined;
}
// Exclude the last property
const props = pivotRowsGrouping.slice(0, pivotRowsGrouping.length - 1);
return { props };
}
let flatHeaders: boolean = pivot ? !!pivot.flatHeaders : false;
let pivotMode: boolean = !!pivot;
let showConfigurator: boolean = pivot ? !!pivot.hasConfigurator : false;
// ---------------------
// Render Function
// ---------------------
function renderTemplate(){
return `
<div class="flex justify-between mb-3 relative" id="topBar">
<div class="flex gap-2">
<span class="flex gap-1" id="leftToggles">
<label>
<input type="checkbox" id="toggleShowConfigurator" />
Show Configurator
</label>
<label class="ml-2">
<input type="checkbox" id="toggleFlatHeaders" />
Flat headers
</label>
<span class="flex ml-2 gap-1" id="rowGroupingToggleContainer">
<label>
<input type="checkbox" id="toggleRowGroupingEnabled" />
Row grouping
</label>
</span>
</span>
</div>
<div class="flex gap-2">
<label>
<input type="checkbox" id="togglePivotMode" />
Pivot Mode
</label>
</div>
</div>
<div class="pivot-grid-container h-full overflow-hidden" id="gridContainer"></div>
`;
}
// ---------------------
// Update Grid Function
// ---------------------
function updateGrid(grid: HTMLRevoGridElement){
grid.additionalData = { pivot };
grid.grouping = getRowGrouping() || {};
}
// ---------------------
// Logic: Event Handlers & Initialization
// ---------------------
export function load(parentSelector: string, rows: any[]){
// Create container and insert rendered HTML
const container = document.createElement('div');
container.innerHTML = renderTemplate();
// Append container to parent element
const parent = document.querySelector(parentSelector);
if (!parent) {
console.error(`Parent element "${parentSelector}" not found.`);
return;
}
parent.appendChild(container);
// Get toggle elements
const togglePivotMode = container.querySelector<HTMLInputElement>('#togglePivotMode');
const toggleShowConfigurator = container.querySelector<HTMLInputElement>('#toggleShowConfigurator');
const toggleFlatHeaders = container.querySelector<HTMLInputElement>('#toggleFlatHeaders');
const toggleRowGroupingEnabled = container.querySelector<HTMLInputElement>('#toggleRowGroupingEnabled');
const leftToggles = container.querySelector<HTMLElement>('#leftToggles');
// Initialize toggle values
if (togglePivotMode) togglePivotMode.checked = pivotMode;
if (toggleShowConfigurator) toggleShowConfigurator.checked = showConfigurator;
if (toggleFlatHeaders) toggleFlatHeaders.checked = flatHeaders;
if (toggleRowGroupingEnabled) toggleRowGroupingEnabled.checked = rowGroupingEnabled;
if (leftToggles) {
leftToggles.style.display = pivotMode ? 'flex' : 'none';
}
// Create and configure the grid element
const gridContainer = container.querySelector<HTMLElement>('#gridContainer');
if (!gridContainer) {
console.error("Grid container not found.");
return;
}
const grid = document.createElement('revo-grid') as HTMLRevoGridElement;
grid.className = "overflow-hidden skip-style h-full";
grid.filter = true;
grid.source = rows;
grid.columns = ECOMMERCE_COLUMNS;
grid.columnTypes = ECOMMERCE_COLUMNS_TYPES;
grid.additionalData = { pivot };
grid.plugins = [PivotPlugin, AdvanceFilterPlugin];
grid.grouping = getRowGrouping() || {};
// Listen for pivot configuration updates from the grid
grid.addEventListener('pivot-config-update', (e: CustomEvent<PivotConfig>) => {
newCfg = e.detail || { ...ECOMMERCE_PIVOT };
pivot = newCfg;
pivotRowsGrouping = newCfg.rows || [];
updateGrid(grid);
});
gridContainer.appendChild(grid);
// Toggle event handlers
if (togglePivotMode) {
togglePivotMode.addEventListener('change', (e) => {
pivotMode = (e.target as HTMLInputElement).checked;
if (pivotMode) {
pivot = newCfg;
} else {
pivot = null;
}
updateGrid(grid);
if (leftToggles) {
leftToggles.style.display = pivotMode ? 'flex' : 'none';
}
});
}
if (toggleShowConfigurator) {
toggleShowConfigurator.addEventListener('change', (e) => {
showConfigurator = (e.target as HTMLInputElement).checked;
if (pivot) {
pivot = { ...pivot, hasConfigurator: showConfigurator };
}
updateGrid(grid);
});
}
if (toggleFlatHeaders) {
toggleFlatHeaders.addEventListener('change', (e) => {
flatHeaders = (e.target as HTMLInputElement).checked;
if (pivot) {
pivot = { ...pivot, flatHeaders: flatHeaders };
}
updateGrid(grid);
});
}
if (toggleRowGroupingEnabled) {
toggleRowGroupingEnabled.addEventListener('change', (e) => {
rowGroupingEnabled = (e.target as HTMLInputElement).checked;
updateGrid(grid);
});
}
}