Table
MetricColumn
A figure read as a measurement: the number, and optionally the trend behind it.
On this page
A figure read as a measurement: the number, and optionally the trend behind it.
use NyonCode\WireTable\Columns\MetricColumn;
How It Works
It aggregates nothing. Dot notation already turns a relation path into a
withCount / withSum subquery, so MetricColumn::make('orders.count') is the
same single query it always was — see Relation Paths.
What this type adds is presentation:
- the figure defaults it shares with MoneyColumn — right-aligned, tabular digits, no wrapping — so numbers line up down the column and the stacked mobile card picks the metric up as its headline figure;
- an optional trend drawn beside the number as a single SVG polyline.
Basic Usage
MetricColumn::make('orders.count')->label('Orders') // withCount, right-alignedMetricColumn::make('items.sum.amount')->label('Volume') // withSumMetricColumn::make('open_tickets') // an ordinary column works too
Adding a trend
MetricColumn::make('orders.count') ->label('Orders') ->trend(fn (Customer $record): array => $record->orders_per_month)
The series is a plain array of numbers in reading order, oldest first. It is drawn by the same geometry a stats widget uses, so a table cell and a dashboard tile show the same shape for the same data.
The series is yours to supply, and that is deliberate
A per-record series cannot be derived from the column's own path: orders per month for this customer is a second query shape, not a formatting of the first. Passing a closure keeps the decision — and the N+1 — where you can see it.
// Right: the series arrives with the page, and the closure only reads it.public function table(Table $table): Table{ return $table ->model(Customer::class) ->query(fn ($query) => $query->withCount('orders')->with('monthlyTotals')) ->columns([ TextColumn::make('name')->sortable(), MetricColumn::make('orders_count') ->label('Orders') ->trend(fn (Customer $r): array => $r->monthlyTotals ->pluck('total')->all()), ]);} // Wrong: this queries once per row, exactly as it reads.->trend(fn (Customer $r): array => $r->orders()->sum('total') ? [] : [])
What a series has to look like
| Series | Drawn as |
|---|---|
[1, 5, 3] |
the curve |
[4, 4, 4] |
a flat line through the middle — steady, not fallen to zero |
[7] |
a flat line; one reading is not a trend, but it is not nothing either |
[4, null, 4] |
the two readings there were — see below |
[] |
nothing at all: the cell is a plain figure |
Non-numeric readings are dropped, not coerced. A null month means "no
reading", and plotting it as 0 invents a crash to the floor and back that
never happened.
Colouring the trend
The stroke follows the column's colour, or one stated for the trend alone:
MetricColumn::make('churn')->color('danger') // both figure and lineMetricColumn::make('orders.count')->trend($series, 'success') // just the line
Overriding the defaults
MetricColumn::make('orders.count') ->alignment('left') // …and it stops being the stacked card's metric ->textSize('lg')
MetricColumn API
->trend(Closure $callback, ?string $color = null) // fn (Model $record): array<int, int|float>->hasTrend(): bool->getTrend(Model $record): array->getTrendColorClass(): string
Everything from TextColumn — formatting, limits, prefixes, summaries — applies unchanged.