Custom Cell Rendering: Badges & Avatars
Rendering trusted HTML - colored status badges, avatar thumbnails - inside a grid cell with Xcrud::html(), plus simpler conditional cell/row styling with highlight().
Why column_callback() alone isn't enough
column_callback($field, $fn) lets you replace a cell's value with whatever your callback returns. By default that return is treated as plain text and escaped, exactly like any other value - so a plain string like '<span>Active</span>' would show up as literal angle brackets, not a styled element.
Wrap the callback's return in the static helper Xcrud::html($html, $text = null) when you need the cell to actually render markup instead:
public static function html(string $html, ?string $text = null): array
| Parameter | Type | Default | Description |
|---|---|---|---|
$html | string | required | The trusted markup to render in the cell (rendered via innerHTML client-side) |
$text | ?string | null | Plain-text fallback; if omitted, defaults to $html with tags stripped |
$text is what actually round-trips as the column's value everywhere styled HTML wouldn't make sense - CSV/XLSX/PDF export, and grid search/sort - since those can't render a colored <span>.
Example: a status badge
A common pattern: color-code a status column with a column_callback() that returns a small pill via Xcrud::html():
$xcrud->column_callback('status', function ($value, $row) {
$colors = [
'active' => '#16a34a',
'pending' => '#d97706',
'canceled' => '#dc2626',
];
$color = $colors[$value] ?? '#6b7280';
$html = '<span style="background:' . $color . ';color:#fff;'
. 'padding:2px 10px;border-radius:999px;font-size:12px;">'
. htmlspecialchars(ucfirst($value)) . '</span>';
return Xcrud::html($html, ucfirst($value));
});
The grid cell shows the colored pill; a CSV/XLSX/PDF export of the same column shows the plain word ("Active", "Pending", "Canceled") instead, and column search/sort still work against that same plain text.
The same approach works for an avatar - return an <img> tag (or an initials-in-a-circle <span>) wrapped in Xcrud::html(), with a plain name or initials as the $text fallback.
highlight() and highlight_row() - simpler conditional styling
When you just need a cell or row to change color based on a comparison - no custom markup required - highlight()/highlight_row() is simpler than a full callback:
public function highlight(string $field, string $operator, string $value, string $class): self
public function highlight_row(string $field, string $operator, string $value, string $class): self
| Parameter | Type | Default | Description |
|---|---|---|---|
$field | string | required | Column to evaluate the condition against |
$operator | string | required | Same vocabulary as where(): symbols or eq/neq/gt/gte/lt/lte/contains/starts/ends |
$value | string | required | Value to compare the field against |
$class | string | required | CSS class applied when the condition matches |
$xcrud->highlight('amount', 'gt', '100000', 'xcrud-hl-warn');
$xcrud->highlight_row('status', 'eq', 'canceled', 'xcrud-hl-muted');
highlight() applies the class to just the matching cell; highlight_row() applies it to the whole row. Multiple rules can match the same cell/row - their classes stack rather than replace each other.