vue-data-view-plus
v0.1.2
Published
Vue 3 components for tables, cards, line charts, and bar charts with typed column definitions.
Maintainers
Readme
vue-data-view-plus
Vue 3 components to present the same dataset in multiple ways—table, card grid, line chart, and bar chart—using one column definition (ColumnsDef) as the single source of truth for labels, types, formatting, and chart eligibility.
Install
npm install vue-data-view-plusPeer dependencies
Install these in your app (versions should satisfy the ranges in this package’s peerDependencies):
vuechart.jsvue-chartjschartjs-adapter-date-fns(used by the line chart for the time axis)date-fns(required bychartjs-adapter-date-fns)
Styles
Import the bundled CSS once (e.g. in main.ts or your app shell):
import "vue-data-view-plus/style.css";If your bundler struggles with the export subpath, use:
import "vue-data-view-plus/dist/style.css";The stylesheet maps design tokens to CSS variables (--vdv-*, with fallbacks to common --color-* / --space-* names). Override those variables in your app to theme tables and charts.
Core idea
items: an array of row objects (TItem extends ColumnObject).columns: a typed array describing every visible column (including a special"actions"column if you need row buttons).- Derived behavior: sorting, pagination, cell text, chart axes, and aggregates all read from that same
columnsmetadata plusitems—you do not configure charts with a second, parallel schema unless you opt in (e.g.filterDefsfor bar-chart categories).
Business logic
This section describes how the library decides what to render and how, not just API names.
Column model
- Each column has a
keymatching a property on the row (unless you usegetValueor the specialactionskey). typedrives:- Default formatting when no custom
formatteris set (tableFormatters). - Sort behavior (numbers, dates, currencies, text).
- Chart eligibility (see below).
- Default formatting when no custom
- Column header text (table, cards, chart axis pickers) uses
resolveColumnDisplayLabel:- If
labelKeyis set,translate(labelKey)is used with the optionaltranslateprop (i18n lookup). - Otherwise
labelis shown as-is (use for literals or already translated text, e.g. Hebrew resolved in the parent).
- If
actionscolumns renderTableActionbuttons; optionaliconis resolved viaiconResolver(e.g. map a string name to a Vue component).
label vs labelKey
| Field | Behavior |
| ----- | -------- |
| label | Display string when labelKey is absent. Not passed through translate. |
| labelKey | Optional. When set (non-empty), the visible title is translate(labelKey). |
You can export resolveColumnDisplayLabel from the package if you need the same rule outside components.
Table & cards (DataTable, DataColumnar)
Sorting
- Clicking a sortable column header toggles asc/desc on that column key.
- Sort uses
getValuewhen present, otherwiserow[key]. - Comparison is type-aware (
number/currency/date/ text).
Pagination
- Operates on the sorted list.
- Page size changes emit
update:pageSize; the parent owns the effective page size if you store it. - When disabled or page size is zero, all sorted rows are shown.
Cells
- Optional named slots per column key override rendering for that column.
- Otherwise
TableCellformats fromtype,format, orformatter. wrapper(text|button|chip|link) chooses the host element;linkuseslinkComponent(e.g.RouterLink) or a plain<a>withhref(row).
Footer totals
- If any column defines
total, a footer row runs those functions on the full sorted dataset (not only the current page).
- If any column defines
Cards repeat the same row/column semantics in a denser layout; actions appear in a footer strip per card.
DataView (unified toggle)
- Renders
table|cards|chart|barChartbased onview(v-model viaupdate:view). - Line chart and bar chart navigation buttons appear only when the respective mode is supported (see helpers below).
- If the requested view becomes invalid (e.g. columns change and charts are no longer possible), the view falls back to
tableandupdate:viewmay emittableto keep parent state consistent.
Line chart (DataChart)
Eligibility (“business rule”): at least one column with type === "date" and one with type === "number" or "currency" (see chartSupported / dataChartSupport).
Behavior:
- X axis uses a chosen date column; Y uses a numeric/currency column.
- Raw points are
(time, value)pairs; invalid dates or numbers are skipped. Group by(granularity none / day / week / month / year) buckets points in local calendar time (same philosophy as Chart.js time scale defaults). Inside each bucket, Y values are combined withaggregateY—defaultsumAggregate—so overlapping rows in the same bucket add up (typical for amounts over time).- Tooltip titles use
formatChartBucketLabelso labels match the granularity.
Peers must include chartjs-adapter-date-fns because the adapter is imported by the component (time scale).
Bar chart (DataBarChart)
Eligibility: at least one categorical X source:
type === "boolean"columns, orDataViewSelectFilterDefentries passed infilterDefs(type: "select"), paired bykey—optionally joined to a real column via the samekey(if the row only holds an id,getValue/ dot-path lookups can still resolve a value).
Ordering of X descriptors: boolean columns first, then select-backed keys; duplicate keys dedupe (boolean wins if both exist—unlikely).
Y axis:
sum/meanneed a numeric/currency column.countcounts rows per category and does not require a numeric column.
Buckets: values are aggregated per category label. Booleans map to yes / no / empty** via **translate**. Select categories use **options()** on the **DataViewSelectFilterDef` for display labels where possible.
See aggregateBarChart, getBarChartXDescriptors, barChartSupported.
Internationalization (translate)
- Components accept optional
translate: (key: string) => string(e.g.vue-i18nt). - Built-in UI strings (toolbar, pagination,
yes/no, chart chrome, …) go through the same helper that applies default English whentranslateis missing, or when a key is unknown. - Column headers do not call
translate(label)anymore. Uselabelfor final text, or setlabelKeyto pass only that string throughtranslate.
Icons (iconResolver)
TableAction.iconmay be a Vue component or an opaque string (your app maps strings to icons if you supplyiconResolver).
Integration props (summary)
| Prop | Role |
|------|------|
| translate | Localize all built-in keys (table, loading, chart strings, pagination, …). |
| iconResolver | Resolve actions[k].icon when icons are strings. |
| linkComponent | e.g. RouterLink; default link behavior otherwise. |
| filterDefs | Bar chart category sources from select filter definitions (DataViewFilterDef[]). |
Quick usage
<script setup lang="ts">
import { DataView, type ColumnsDef } from "vue-data-view-plus";
interface Row extends Record<string, unknown> {
id: number;
name: string;
amount: number;
createdAt: string;
}
const items: Row[] = [
/* ... */
];
const columns = [
{ key: "name", label: "Name", type: "text" },
{ key: "amount", label: "Amount", type: "currency" },
{
key: "createdAt",
label: "Created",
type: "date",
format: "datetime",
},
] as const satisfies ColumnsDef<Row>;
</script>
<template>
<DataView
:items="items"
:columns="columns"
:translate="(k) => k"
:show-view-toggle="true"
/>
</template>Pass translate from vue-i18n, iconResolver, and link-component in real apps.
Exported utilities
Use these when you want the same rules outside the UI (e.g. feature flags or server docs):
| Export | Purpose |
|--------|---------|
| chartSupported, getDateColumnKeys, getNumericColumnKeys | Line-chart column detection. |
| barChartSupported, getBarChartXDescriptors | Bar-chart category detection (+ filterDefs). |
| aggregateBarChart | Same aggregation as DataBarChart. |
| aggregateTimeSeriesPoints, formatChartBucketLabel, sumAggregate, … | Line-chart bucketing. |
| formatCell, getCellValue, getRowId | Table/card formatting and identity. |
| resolveColumnDisplayLabel, ColumnLikeForLabel | Same label / labelKey title rules as the UI. |
| useTableSort, useTablePagination | Headless sort/pagination. |
Build from source
In this repo’s package folder:
npm run build
npm testprepublishOnly runs npm run build before npm publish.
License
Set the SPDX identifier in this package’s package.json license field when you publish (for example "MIT").
