Skip to main content Skip to footer

Disable a PivotPanel Checkbox Field in React

Checkboxes disabled in PivotPanel

Background:

Sometimes, you may want to disable the checkbox of a specific field in your PivotPanel to prevent users from interacting with it.

Steps to Complete:

  1. Create the PivotEngine
  2. Track which fields to disable
  3. Render the PivotPanel
  4. Disable checkboxes via the fields grid’s formatItem

Getting Started:

Create the PivotEngine

Build the engine the Panel/Grid will share.

// src/olap/data.ts
export type OrderRow = {
  Country: string; Category: string; Product: string;
  Amount: number; Quantity: number; Date: Date;
};

export function makeData(rows = 200): OrderRow[] {
  const countries = ['US', 'UK', 'Germany', 'Japan'];
  const cats = ['Electronics', 'Clothing'];
  const prods: Record<string, string[]> = {
    Electronics: ['Phone', 'Laptop', 'Tablet'],
    Clothing: ['Shirt', 'Jacket', 'Jeans'],
  };
  const out: OrderRow[] = [];
  for (let i = 0; i < rows; i++) {
    const c = countries[(Math.random() * countries.length) | 0];
    const cat = cats[(Math.random() * cats.length) | 0];
    const p = prods[cat][(Math.random() * prods[cat].length) | 0];
    out.push({
      Country: c, Category: cat, Product: p,
      Amount: +(Math.random() * 1000).toFixed(2),
      Quantity: 1 + (Math.random() * 10) | 0,
      Date: new Date(2024, (Math.random() * 12) | 0, 1 + (Math.random() * 28) | 0),
    });
  }
  return out;
}
// src/olap/engine.ts
import * as wjOlap from '@mescius/wijmo.olap';
import { makeData } from './data';

export function createEngine(): wjOlap.PivotEngine {
  return new wjOlap.PivotEngine({
    itemsSource: makeData(),
    fields: [
      { binding: 'Country', header: 'Country' },
      { binding: 'Category', header: 'Category' },
      { binding: 'Product',  header: 'Product'  },
      { binding: 'Amount',   header: 'Amount',   format: 'n2' },
      { binding: 'Quantity', header: 'Quantity' },
      { binding: 'Date',     header: 'Date'     },
    ],
    rowFields: ['Country'],
    valueFields: ['Amount', 'Quantity'],
  });
}

 

Track which fields to disable

Central list of protected field headers.

// inside your React component file
const [disabledFields] = React.useState<string[]>(['Amount']); // edit as needed

 

Render the PivotPanel and PivotGrid

Create refs and bind the shared engine.

// src/App.tsx
import React from 'react';
import * as wjOlap from '@mescius/wijmo.olap';
import { PivotPanel, PivotGrid } from '@mescius/wijmo.react.olap';
import { createEngine } from './olap/engine';

export default function App() {
  const panelRef = React.useRef<any>(null);
  const engine = React.useMemo<wjOlap.PivotEngine>(() => createEngine(), []);

  const [disabledFields] = React.useState<string[]>(['Amount']);

  // next steps will add effects here…

  return (
    <div style={{ fontFamily: 'system-ui, Segoe UI, Arial', padding: 16 }}>
      <h2>Wijmo PivotPanel (React) — Disable specific field checkboxes</h2>

      <PivotPanel ref={panelRef} itemsSource={engine} />
      <PivotGrid itemsSource={engine} />

      <p>Disabled fields: <code>{disabledFields.join(', ')}</code></p>
    </div>
  );
}

 

Disable checkboxes via the fields grid’s formatItem

Hook the internal fields list grid (_lbFields) formatItem and disable the <input type="checkbox"> when the field header matches.

// add inside App() after refs/state
React.useEffect(() => {
  const panel = panelRef.current?.control as wjOlap.PivotPanel | undefined;
  const fieldsGrid = (panel as any)?._lbFields; // private; may change across versions
  if (!fieldsGrid?.formatItem) return;

  const handler = (s: any, e: any) => {
    if (e.panel === s.cells) {
      const row = e.getRow();
      const col = e.getColumn();
      const header = row?.dataItem?.[col?.binding];
      if (disabledFields.includes(header)) {
        const chk: HTMLInputElement | null = e.cell.querySelector('input[type="checkbox"]');
        if (chk) chk.disabled = true; // why: prevent toggling protected fields
      }
    }
  };

  fieldsGrid.formatItem.addHandler(handler);
  return () => fieldsGrid.formatItem.removeHandler(handler);
}, [disabledFields]);

  

If implemented correctly, your checkboxes should now be disabled/protected. I hope you find this article helpful. Happy coding!

 

Full code file to reference:

// src/App.tsx
import React from 'react';
import * as wjOlap from '@mescius/wijmo.olap';
import { PivotPanel, PivotGrid } from '@mescius/wijmo.react.olap';

// -------- data helpers ----------
type OrderRow = {
  Country: string; Category: string; Product: string;
  Amount: number; Quantity: number; Date: Date;
};

function makeData(rows = 200): OrderRow[] {
  const countries = ['US', 'UK', 'Germany', 'Japan'];
  const cats = ['Electronics', 'Clothing'];
  const prods: Record<string, string[]> = {
    Electronics: ['Phone', 'Laptop', 'Tablet'],
    Clothing: ['Shirt', 'Jacket', 'Jeans'],
  };
  const out: OrderRow[] = [];
  for (let i = 0; i < rows; i++) {
    const c = countries[(Math.random() * countries.length) | 0];
    const cat = cats[(Math.random() * cats.length) | 0];
    const p = prods[cat][(Math.random() * prods[cat].length) | 0];
    out.push({
      Country: c, Category: cat, Product: p,
      Amount: +(Math.random() * 1000).toFixed(2),
      Quantity: 1 + (Math.random() * 10) | 0,
      Date: new Date(2024, (Math.random() * 12) | 0, 1 + (Math.random() * 28) | 0),
    });
  }
  return out;
}

function createEngine(): wjOlap.PivotEngine {
  return new wjOlap.PivotEngine({
    itemsSource: makeData(),
    fields: [
      { binding: 'Country', header: 'Country' },
      { binding: 'Category', header: 'Category' },
      { binding: 'Product',  header: 'Product'  },
      { binding: 'Amount',   header: 'Amount',   format: 'n2' },
      { binding: 'Quantity', header: 'Quantity' },
      { binding: 'Date',     header: 'Date'     },
    ],
    rowFields: ['Country'],
    valueFields: ['Amount', 'Quantity'],
  });
}

export default function App() {
  const panelRef = React.useRef<any>(null);
  const engine = React.useMemo<wjOlap.PivotEngine>(() => createEngine(), []);

  // fields to protect
  const [disabledFields] = React.useState<string[]>(['Amount']);

  // disable checkboxes in the fields list
  React.useEffect(() => {
    const panel = panelRef.current?.control as wjOlap.PivotPanel | undefined;
    const fieldsGrid = (panel as any)?._lbFields;
    if (!fieldsGrid?.formatItem) return;

    const handler = (s: any, e: any) => {
      if (e.panel === s.cells) {
        const row = e.getRow();
        const col = e.getColumn();
        const header = row?.dataItem?.[col?.binding];
        if (disabledFields.includes(header)) {
          const chk: HTMLInputElement | null = e.cell.querySelector('input[type="checkbox"]');
          if (chk) chk.disabled = true; // why: make protected fields non-toggleable
        }
      }
    };

    fieldsGrid.formatItem.addHandler(handler);
    return () => fieldsGrid.formatItem.removeHandler(handler);
  }, [disabledFields]);

  // optional: block "Remove Field" in context menu
  React.useEffect(() => {
    const panel = panelRef.current?.control as wjOlap.PivotPanel | undefined;
    if (!panel) return;

    try {
      const MenuProto = (wjOlap as any)._ListContextMenu?.prototype;
      if (MenuProto && !MenuProto.__patched && MenuProto._canExecute) {
        const original = MenuProto._canExecute;
        MenuProto._canExecute = function (this: any, cmd: string) {
          const isRemove = /remove(field)?/i.test(cmd ?? '');
          const header = this?._targetField?.header;
          const owner = (this?.ownerPivotPanel ?? this?.hostPivotPanel)?.owner;
          if (isRemove && header && owner?.disabledFields?.includes(header)) return false;
          return original.apply(this, arguments as any);
        };
        MenuProto.__patched = true;
        (panel as any).owner = { disabledFields }; // surface to menu
      }
    } catch { /* ignore if internals differ */ }
  }, [disabledFields]);

  return (
    <div style={{ fontFamily: 'system-ui, Segoe UI, Arial', padding: 16 }}>
      <h2>Wijmo PivotPanel (React) — Disable specific field checkboxes</h2>
      <PivotPanel ref={panelRef} itemsSource={engine} />
      <PivotGrid itemsSource={engine} />
      <p>Disabled fields: <code>{disabledFields.join(', ')}</code></p>
    </div>
  );
}

Andrew Peterson

Technical Engagement Engineer