Embed an Editable Dashboard in Your React, Vue or Angular App
One npm package with a grid layout engine, a widget wizard and a JSON config you can store
By Vincenzo Manto, founder of Datastripes · Published 19 October 2026 · Updated 19 October 2026Customers like dashboards they can rearrange. Building one yourself means a grid system, a catalog of charts, a settings form, filters and a way to save the layout, and that list is longer than it looks from the outside.@datastripes/dashboard packages those pieces. You pass it an array of rows and a JSON config, and it renders a dashboard that users can edit, filter and export. This page covers how the config works, how to embed the dashboard in each framework, and what the package leaves to you.
One package, four entry points
The root entry, @datastripes/dashboard, is the core engine: schema, query engine, grid engine, store, widget logic and licensing. It needs nothing else. On top of it sit a React entry with a <DatastripesDashboard> component (React 19), a Vue entry for Vue 3.4 and later, an Angular entry with a standalone DatastripesDashboardComponent (Angular 18 or 19), and an /elements entry that registers a <datastripes-dashboard> custom element.The UI frameworks are optional peer dependencies, so installing the package never pulls one in.npm install @datastripes/dashboardThe dashboard is a JSON document
Everything about a dashboard lives in one config object: a version, settings with the grid layout, global filters, calculated fields, column labels and a list of widgets. Each widget has a type, a position on the grid and a query.import { DashboardStore, JsQueryEngine, parseDashboardConfig } from '@datastripes/dashboard';
const config = parseDashboardConfig({
version: '1.0.0',
settings: { title: 'Sales', layout: { columns: 12, rowHeight: 60, gutter: 16 } },
globalFilters: [],
calculatedFields: [],
columnLabels: {},
widgets: [
{
id: 'kpi_revenue',
type: 'kpi_card',
title: 'Total Revenue',
grid: { x: 0, y: 0, w: 3, h: 2 },
dataQuery: { metrics: [{ field: 'amount', aggregation: 'sum', alias: 'amount' }] },
renderConfig: { format: 'currency' },
},
],
});
const store = new DashboardStore({ config, data: myRows, engine: new JsQueryEngine() });The grid here is twelve columns wide with 60 pixel rows. The single widget sits at the top left corner, three columns wide and two rows tall, and sums the amount column. Because the config is plain JSON, you can store it next to the user's account and load it back later.Embedding it in React
In React the config and the data go in as props. In edit mode the user can change the layout, and the component reports every change back to you.import { DatastripesDashboard } from '@datastripes/dashboard/react';
import type { DashboardConfig } from '@datastripes/dashboard';
function App() {
const [config, setConfig] = useState<DashboardConfig | undefined>();
return (
<DatastripesDashboard
data={myRows}
config={config}
mode="edit"
apiKey={import.meta.env.VITE_DATASTRIPES_KEY}
onChange={setConfig}
onSave={(saved) => persistToBackend(saved)}
onAction={(event) => console.log(event)}
/>
);
}In edit mode the toolbar has an Add widget button that opens a short wizard. The user picks a widget type, then a chart kind from the catalog of 25, then fields, colors and axis labels. The gear icon on an existing widget reopens the same form. The toolbar also offers a light and dark switch, PDF export and a period navigator.onSave fires when the user clicks Save, which is where you persist the config. onAction delivers row_click and filter_change events, which is how you connect drill-down and cross-filtering to the rest of your app.What users can change without you
The settings panel lets users adjust number formatting, define calculated fields and rename columns. That covers a lot of the requests that usually come back to a developer: show this as a percentage, add a margin column, call the field something readable. Because those choices end up in the config, they are saved and restored with the layout.Filters work at two levels. Global filters in the config apply across the dashboard, and a filter panel widget lets the user change them in place.Vue, Angular and plain HTML
Vue uses a DatastripesDashboard single file component and Angular a standalone DatastripesDashboardComponent. For any other stack the custom element works straight from a script tag.<script src="https://unpkg.com/@datastripes/dashboard/dist/elements/index.global.js"></script>
<datastripes-dashboard id="dash" mode="edit" api-key="..."></datastripes-dashboard>
<script>
const el = document.getElementById('dash');
el.data = myRows; // set as a property for large datasets
el.config = myConfig; // DashboardConfig object
el.addEventListener('ds-change', (e) => console.log(e.detail));
el.addEventListener('ds-action', (e) => console.log(e.detail));
</script>