v1.2.0

Preact data table

Table, Bro is the Custom Element ‹table-bro›, so a Preact app renders it in JSX as it is. A ref gives the element its columns, rows and config by configure(), the prop onbro-action listens to its events, and the theme prop sets its theme. The page below is the working page of the sample project samples/frameworks/preact of the repository, with Preact 11; StackBlitz opens it in the browser.

Loading
Items per page:
Clear

How do I install Table, Bro in Preact?

  1. Install the packages

    The table engine @table-bro/core and a skin, @table-bro/native of plain HTML elements; @table-bro/bootstrap with bootstrap gives the skin of Bootstrap 5:

    npm install @table-bro/core @table-bro/native
    
  2. Register the element and the skin

    Once, before the tables: the import of the skin defines ‹table-bro› and registers the skin nv. The CSS of the core and of the skin come as imports, which Vite and the other bundlers take. src/skin.ts:

    // The CSS of the core and of the skin, then the skin: its import defines <table-bro> and registers the skin nv
    import '@table-bro/core/dist/table-bro.min.css';
    import '@table-bro/native/dist/table-bro.native.min.css';
    import '@table-bro/native';
    
    import './sample-page.css';
    
  3. Describe the columns, the rows and the config

    conf.skin names the registered skin. src/orders.ts:

    import type {BroCol, BroConfig, BroRow} from '@table-bro/core';
    
    export interface Order extends BroRow {
      description: string;
      price: number;
    }
    
    export const cols: BroCol<Order>[] = [
      {
        title: 'Description',
        name: 'description'
      }, {
        title: 'Price',
        name: 'price',
        dataType: 'number',
        className: 'bro-col_text-right'
      }
    ];
    
    export const rows: Order[] = [
      {
        description: 'Modern Cotton Chair',
        price: 100
      }, {
        description: 'Awesome Concrete Ball',
        price: 200
      }
    ];
    
    export const conf: BroConfig = {
      skin: 'nv',
      toolbarTitle: 'Orders'
    };
    

How do I pass cols, rows and conf?

The columns, the rows and the config go to the table in one call, configure({cols, rows, conf}), once the element is in the document: a ref gives the element, useEffect makes the call. Preact adds a listener for an event prop it does not know by the exact name after on, bro-action for onbro-action (Preact, Web Components); the sample logs the name of each action. src/OrdersTable.tsx:

import {useEffect, useRef} from 'preact/hooks';

import type {BroActionDetail, TableBroHTMLElement} from '@table-bro/core';

import {cols, conf, rows} from './orders';

export function OrdersTable() {
  const table = useRef<TableBroHTMLElement>(null);

  useEffect(() => {
    table.current!.configure({cols, rows, conf});
  }, []);

  return (
    <div class="bro-table-shadow-container">
      <table-bro id="orders" ref={table} theme="auto"
                 onbro-action={(event: CustomEvent<BroActionDetail>) => console.log(event.detail.action)}></table-bro>
    </div>
  );
}

"jsxImportSource": "preact" in tsconfig.json of the sample gives the JSX runtime of Preact to TypeScript and to Vite, without a plugin.

How does TypeScript know the element?

A declaration adds ‹table-bro› to the JSX of Preact, with the methods of TableBroHTMLElement and the prop onbro-action. src/elements.d.ts:

// The element <table-bro> in the JSX of Preact, with its attribute theme and its event bro-action
import type {HTMLAttributes} from 'preact';

import type {BroActionDetail, TableBroHTMLElement} from '@table-bro/core';

declare module 'preact' {
  namespace JSX {
    interface IntrinsicElements {
      'table-bro': HTMLAttributes<TableBroHTMLElement> & {theme?: 'light' | 'dark' | 'auto'; 'onbro-action'?: (event: CustomEvent<BroActionDetail>) => void};
    }
  }
}

How do I render it?

src/main.tsx imports the skin before the tables:

// The skin is registered before the tables
import './skin';

import {render} from 'preact';

import {OrdersTable} from './OrdersTable';

render(<OrdersTable />, document.getElementById('app')!);

How do I switch the theme?

The theme attribute or property of the table is 'light', 'dark' or 'auto', which follows the color scheme of the system; the attribute wins over config.theme. The sample sets 'auto', as a table without the attribute does; a variable of the state bound to it switches the theme, and the table puts the class bro-dark-theme or bro-light-theme on itself. More in Dark/Light mode.

Questions

Does Preact need a wrapper for Custom Elements?

No. Preact passes all 32 tests of Custom Elements Everywhere. Its package preact-custom-element also turns a Preact component into a Custom Element (Preact, preact-custom-element).

Can I bind cols and rows as props?

The table takes its data by configure(), one call for the columns, the rows and the config. New rows go by replaceRows(rows) on the same ref.

Does preact/compat change it?

No: ‹table-bro› is an element of the DOM, the same in Preact and in React through preact/compat.

Related

Getting started, Custom content in tables using Custom Elements, MCP server for AI coding agents, Angular data table, React data table, Solid data table, Svelte data table, Vue 3 data table.

DJ