Table, Bro is the Custom Element ‹table-bro›, so a Vue 3 app renders it in a template once the compiler knows the tag: compilerOptions.isCustomElement of @vitejs/plugin-vue. A template ref gives the element its columns, rows and config by configure(), @bro-action listens to its events, and the theme attribute sets its theme. The page below is the working page of the sample project samples/frameworks/vue of the repository, with Vue 3.5; StackBlitz opens it in the browser.
No
| Description
| Price
|
|---|
|
|
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
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';
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'
};
Without it, Vue resolves ‹table-bro› as a component of the app and warns that it fails. isCustomElement of the template compiler skips the tags of Table, Bro (Vue, Using Custom Elements in Vue). vite.config.ts:
import vue from '@vitejs/plugin-vue';
import {defineConfig, mergeConfig} from 'vite';
import {samplePage} from './sample-page.config.ts';
export default mergeConfig(samplePage, defineConfig({
plugins: [
// Vue compiles <table-bro> of its templates as a Custom Element, not as a component of Vue
vue({template: {compilerOptions: {isCustomElement: tag => tag.startsWith('table-bro')}}})
]
}));
mergeConfig adds sample-page.config.ts of the sample, the source maps and the readable code of its working page; a project of its own exports defineConfig() with the plugins alone.
The columns, the rows and the config go to the table in one call, configure({cols, rows, conf}), once the element is mounted: useTemplateRef gives the element, onMounted makes the call. @bro-action adds the listener of the event, which logs the name of each action, and theme sets the theme; a binding :theme goes to the property theme of the element, since Vue sets a binding of a custom element as a property when the element has it. src/OrdersTable.vue:
<script setup lang="ts">
import {onMounted, useTemplateRef} from 'vue';
import type {BroActionDetail, TableBroHTMLElement} from '@table-bro/core';
import {cols, conf, rows} from './orders';
const table = useTemplateRef<TableBroHTMLElement>('table');
onMounted(() => table.value!.configure({cols, rows, conf}));
function onAction(event: CustomEvent<BroActionDetail>) {
console.log(event.detail.action);
}
</script>
<template>
<div class="bro-table-shadow-container">
<table-bro id="orders" ref="table" theme="auto" @bro-action="onAction"></table-bro>
</div>
</template>
src/main.ts imports the skin before the tables:
// The skin is registered before the tables
import './skin';
import {createApp} from 'vue';
import OrdersTable from './OrdersTable.vue';
createApp(OrdersTable).mount('#app');
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.
No. Vue passes all 32 tests of Custom Elements Everywhere; it only needs isCustomElement for the tags of Table, Bro.
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.
The element needs the browser: render the component on the client, as ‹ClientOnly› does; isCustomElement goes to vue.compilerOptions of nuxt.config.ts.
Getting started, Custom content in tables using Custom Elements, MCP server for AI coding agents, Angular data table, Preact data table, React data table, Solid data table, Svelte data table.
We use Google Analytics to understand how you use our site and to make it better.
Learn more in our Privacy Policy