Data Grid
Data Grid is a higher-level companion to Table: an accessible data grid with column sorting, searching, row selection, sticky headers, and both client-side and server-driven state, all built in rather than assembled by hand. It renders a native <table>, so every interaction, sorting, selecting, paging, searching, happens through real, independently keyboard-operable controls rather than a hand-rolled widget.
| ORD-1041 | Kofi Addo | Paid | $61.97 | |
| ORD-1042 | Akosua Owusu | Paid | $98.94 | |
| ORD-1043 | Ama Mensah | Paid | $135.91 | |
| ORD-1044 | Yaw Boateng | Pending | $172.88 | |
| ORD-1045 | Efua Asante | Paid | $29.85 | |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 | |
| ORD-1047 | Abena Darko | Pending | $103.79 | |
| ORD-1048 | Kwabena Osei | Paid | $140.76 | |
| ORD-1049 | Adjoa Frimpong | Paid | $177.73 | |
| ORD-1050 | Kojo Asante | Pending | $34.70 | |
| ORD-1051 | Akua Sarpong | Paid | $71.67 | |
| ORD-1052 | Yaa Amponsah | Paid | $108.64 | |
| ORD-1053 | Kwesi Appiah | Paid | $145.61 | |
| ORD-1054 | Afia Boadu | Pending | $182.58 | |
| ORD-1055 | Kwaku Antwi | Paid | $39.55 | |
| ORD-1056 | Esi Danso | Refunded | $76.52 | |
| ORD-1057 | Kofi Addo | Pending | $113.49 | |
| ORD-1058 | Akosua Owusu | Paid | $150.46 | |
| ORD-1059 | Ama Mensah | Paid | $187.43 | |
| ORD-1060 | Yaw Boateng | Pending | $44.40 | |
| ORD-1061 | Efua Asante | Paid | $81.37 | |
| ORD-1062 | Kwame Nkrumah Jr. | Paid | $118.34 | |
| ORD-1063 | Abena Darko | Paid | $155.31 | |
| ORD-1064 | Kwabena Osei | Pending | $192.28 | |
| ORD-1065 | Adjoa Frimpong | Paid | $49.25 | |
| ORD-1066 | Kojo Asante | Refunded | $86.22 | |
| ORD-1067 | Akua Sarpong | Pending | $123.19 | |
| ORD-1068 | Yaa Amponsah | Paid | $160.16 | |
| ORD-1069 | Kwesi Appiah | Paid | $197.13 | |
| ORD-1070 | Afia Boadu | Pending | $54.10 | |
| ORD-1071 | Kwaku Antwi | Paid | $91.07 | |
| ORD-1072 | Esi Danso | Paid | $128.04 | |
| ORD-1073 | Kofi Addo | Paid | $165.01 | |
| ORD-1074 | Akosua Owusu | Pending | $201.98 | |
| No records found. | ||||
<x-bladewind::data-grid
name="orders-grid"
label="Orders"
searchable="true"
selectable="true"
sortable="true"
paginated="true"
page-size="10"
:columns="[
['key' => 'reference', 'label' => 'Reference', 'sortable' => true],
['key' => 'customer', 'label' => 'Customer', 'sortable' => true],
['key' => 'status', 'label' => 'Status', 'align' => 'center', 'format' => $statusPill],
['key' => 'total', 'label' => 'Total', 'align' => 'right', 'sortable' => true,
'format' => fn ($value) => '$'.number_format($value / 100, 2)],
]"
:rows="$orders" />
The example above uses 34 orders, enough for four real pages at the default page size, so paging, sorting, and searching all have something genuine to work against instead of a handful of rows that fit on one screen anyway.
Columns and Rows
Each column accepts key, label, align, width, sortable, class, and two callbacks: format($value, $row) for display, and sort($value, $row) for when the sortable value should differ from the displayed one. rows is an array of associative arrays or objects; a row's identity comes from row-key, which defaults to id.
Shorthand Column Syntax
Writing out ['key' => 'name', 'label' => 'Name'] for every column is tedious when you just want the label auto-generated from the key. Pass a plain array of key strings instead, and the grid title-cases each key and swaps underscores for spaces to build the label.
Shorthand columns skip the format and sort callbacks entirely, so cells render whatever raw value the field holds. That is fine for text and status fields, and the reason the example below leaves total out: an unformatted amount in cents is not something you would want to ship.
<x-bladewind::data-grid name="short-columns" label="Reviewers"
:columns="['reference', 'customer', 'status']"
:rows="$orders" />
| reference | customer | status |
|---|---|---|
| ORD-1041 | Kofi Addo | paid |
| ORD-1042 | Akosua Owusu | paid |
| ORD-1043 | Ama Mensah | paid |
| ORD-1044 | Yaw Boateng | pending |
| No records found. | ||
You can also pass an associative array of key => label pairs when you only need to rename a column, without the full array shape.
<x-bladewind::data-grid name="aliased-columns" label="Reviewers"
:columns="['reference' => 'Order #', 'customer' => 'Placed By', 'status' => 'State']"
:rows="$orders" />
| Order # | Placed By | State |
|---|---|---|
| ORD-1041 | Kofi Addo | paid |
| ORD-1042 | Akosua Owusu | paid |
| ORD-1043 | Ama Mensah | paid |
| ORD-1044 | Yaw Boateng | pending |
| No records found. | ||
Formatting a Column
format($value, $row) receives the raw cell value and the full row, and its return value is rendered as raw HTML rather than escaped text. That means a format callback can return a styled badge, an icon, or a link, not just a plain string. The Status column in the orders grid above uses exactly this to render a colour-coded pill:
$statusColors = [
'paid' => 'bg-emerald-100 text-emerald-700',
'pending' => 'bg-amber-100 text-amber-700',
'refunded' => 'bg-slate-200 text-slate-600',
];
$columns = [
// ...
[
'key' => 'status',
'label' => 'Status',
'align' => 'center',
'format' => function ($value) use ($statusColors) {
$class = $statusColors[$value] ?? $statusColors['pending'];
return '<span class="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium '.$class.'">'
.ucfirst($value).'</span>';
},
],
];
format output is not escaped, never feed it raw user input without sanitising first. Build the HTML yourself around a trusted value, as above, or run untrusted text through e() before it goes into the string.Custom Sort Values
Sorting compares the raw cell value by default, before format runs. That is correct for the currency column above, since total is already an integer number of cents. It breaks down for a column whose sortable order should not match either the raw value or the formatted text, a date stored as a display string, or a status that should sort by severity rather than alphabetically. Give the column its own sort($value, $row) callback to override just the comparison value.
<x-bladewind::data-grid name="status-priority" label="Orders by priority" sortable="true"
:columns="[
['key' => 'reference', 'label' => 'Reference'],
['key' => 'status', 'label' => 'Status', 'align' => 'center',
'format' => $statusPill,
'sort' => fn ($value) => ['refunded' => 0, 'pending' => 1, 'paid' => 2][$value] ?? 1],
]"
:rows="$orders" />
| ORD-1041 | Kofi Addo | Paid |
| ORD-1042 | Akosua Owusu | Paid |
| ORD-1043 | Ama Mensah | Paid |
| ORD-1044 | Yaw Boateng | Pending |
| ORD-1045 | Efua Asante | Paid |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded |
| ORD-1047 | Abena Darko | Pending |
| ORD-1048 | Kwabena Osei | Paid |
| ORD-1049 | Adjoa Frimpong | Paid |
| ORD-1050 | Kojo Asante | Pending |
| ORD-1051 | Akua Sarpong | Paid |
| ORD-1052 | Yaa Amponsah | Paid |
| ORD-1053 | Kwesi Appiah | Paid |
| ORD-1054 | Afia Boadu | Pending |
| ORD-1055 | Kwaku Antwi | Paid |
| ORD-1056 | Esi Danso | Refunded |
| ORD-1057 | Kofi Addo | Pending |
| ORD-1058 | Akosua Owusu | Paid |
| ORD-1059 | Ama Mensah | Paid |
| ORD-1060 | Yaw Boateng | Pending |
| ORD-1061 | Efua Asante | Paid |
| ORD-1062 | Kwame Nkrumah Jr. | Paid |
| ORD-1063 | Abena Darko | Paid |
| ORD-1064 | Kwabena Osei | Pending |
| ORD-1065 | Adjoa Frimpong | Paid |
| ORD-1066 | Kojo Asante | Refunded |
| ORD-1067 | Akua Sarpong | Pending |
| ORD-1068 | Yaa Amponsah | Paid |
| ORD-1069 | Kwesi Appiah | Paid |
| ORD-1070 | Afia Boadu | Pending |
| ORD-1071 | Kwaku Antwi | Paid |
| ORD-1072 | Esi Danso | Paid |
| ORD-1073 | Kofi Addo | Paid |
| ORD-1074 | Akosua Owusu | Pending |
| No records found. | ||
Click the Status header above: refunded orders sort first, then pending, then paid, even though the visible text is a badge rather than the plain word the sort actually compares.
Row Identity
Every row needs a stable, unique key so selection, sorting, and pagination can track it across re-renders. By default the grid reads id off each row. Set row-key when your data's identifier is called something else, an order reference, a UUID column, a database primary key with a different name.
<x-bladewind::data-grid name="by-reference" label="Orders" row-key="reference"
:columns="$orderColumns" :rows="$orders" />
Sorting
Set sortable="true" on the grid to make every column sortable, or set sortable per column, as the Reference and Customer columns do in the first example on this page. Clicking a header cycles none, ascending, descending, none again.
client-sort defaults to true and reorders rows in the browser. Set it to false for a server-driven grid: clicking a header only updates the arrow indicator and emits bladewind:data-grid:sort-change, leaving the actual reordering to the application.Sorting on Load
Pass sort-key and sort-direction to render the grid already sorted, useful for a grid that should default to showing the newest or highest-value rows first without the user having to click anything.
<x-bladewind::data-grid name="highest-value-first" label="Orders by value"
sortable="true" sort-key="total" sort-direction="desc"
:columns="$orderColumns" :rows="$orders" />
| ORD-1041 | Kofi Addo | Paid | $61.97 |
| ORD-1042 | Akosua Owusu | Paid | $98.94 |
| ORD-1043 | Ama Mensah | Paid | $135.91 |
| ORD-1044 | Yaw Boateng | Pending | $172.88 |
| ORD-1045 | Efua Asante | Paid | $29.85 |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 |
| ORD-1047 | Abena Darko | Pending | $103.79 |
| ORD-1048 | Kwabena Osei | Paid | $140.76 |
| ORD-1049 | Adjoa Frimpong | Paid | $177.73 |
| ORD-1050 | Kojo Asante | Pending | $34.70 |
| ORD-1051 | Akua Sarpong | Paid | $71.67 |
| ORD-1052 | Yaa Amponsah | Paid | $108.64 |
| ORD-1053 | Kwesi Appiah | Paid | $145.61 |
| ORD-1054 | Afia Boadu | Pending | $182.58 |
| ORD-1055 | Kwaku Antwi | Paid | $39.55 |
| ORD-1056 | Esi Danso | Refunded | $76.52 |
| ORD-1057 | Kofi Addo | Pending | $113.49 |
| ORD-1058 | Akosua Owusu | Paid | $150.46 |
| ORD-1059 | Ama Mensah | Paid | $187.43 |
| ORD-1060 | Yaw Boateng | Pending | $44.40 |
| ORD-1061 | Efua Asante | Paid | $81.37 |
| ORD-1062 | Kwame Nkrumah Jr. | Paid | $118.34 |
| ORD-1063 | Abena Darko | Paid | $155.31 |
| ORD-1064 | Kwabena Osei | Pending | $192.28 |
| ORD-1065 | Adjoa Frimpong | Paid | $49.25 |
| ORD-1066 | Kojo Asante | Refunded | $86.22 |
| ORD-1067 | Akua Sarpong | Pending | $123.19 |
| ORD-1068 | Yaa Amponsah | Paid | $160.16 |
| ORD-1069 | Kwesi Appiah | Paid | $197.13 |
| ORD-1070 | Afia Boadu | Pending | $54.10 |
| ORD-1071 | Kwaku Antwi | Paid | $91.07 |
| ORD-1072 | Esi Danso | Paid | $128.04 |
| ORD-1073 | Kofi Addo | Paid | $165.01 |
| ORD-1074 | Akosua Owusu | Pending | $201.98 |
| No records found. | |||
Server-Driven Sorting
With client-sort="false", clicking a sortable header does not touch the DOM. It fires a cancelable before-sort-change followed by sort-change, with the column key and the new direction in the event detail. Handle it, refetch the sorted page from your backend, and re-render the grid, the same pattern used by the search and pagination events further down this page.
document.addEventListener('bladewind:data-grid:sort-change', (event) => {
if (event.detail.name !== 'orders-grid') return;
const { key, direction } = event.detail;
setDataGridLoading('orders-grid', true);
fetch(`/orders?sort=${key}&direction=${direction}`)
.then((response) => response.text())
.then((html) => {
document.getElementById('orders-grid-wrapper').innerHTML = html;
});
});
Searching
searchable="true" renders a toolbar search field. client-search defaults to true and filters rows by their rendered cell text as you type. Try searching for a customer name in the first example on this page, or for a status like refunded.
Customise the placeholder with search-placeholder:
<x-bladewind::data-grid name="orders-grid" searchable="true" search-placeholder="Search by reference or customer…"
:columns="$orderColumns" :rows="$orders" />
Server-Driven Searching
Set client-search="false" to filter server-side instead. The grid renders no filtering itself, it emits bladewind:data-grid:search with the current query on every keystroke, so debounce it yourself before hitting your backend.
let searchTimer;
document.addEventListener('bladewind:data-grid:search', (event) => {
if (event.detail.name !== 'orders-grid') return;
clearTimeout(searchTimer);
searchTimer = setTimeout(() => {
setDataGridLoading('orders-grid', true);
fetch(`/orders?q=${encodeURIComponent(event.detail.query)}`)
.then((response) => response.text())
.then((html) => {
document.getElementById('orders-grid-wrapper').innerHTML = html;
});
}, 300);
});
Row Selection
selectable="true" adds a selection column. selection-mode is multiple (checkboxes, with a tri-state select-all in the header, scoped to the current page or search results) or single (radio buttons). A selection bar appears above the grid once anything is selected, with a clear-selection control and an optional bulk-actions slot for custom buttons.
Multiple Selection
<x-bladewind::data-grid name="bulk-orders" label="Orders" selectable="true" selection-mode="multiple"
paginated="true" page-size="8" :columns="$orderColumns" :rows="$orders" />
| Status | ||||
|---|---|---|---|---|
| ORD-1041 | Kofi Addo | Paid | $61.97 | |
| ORD-1042 | Akosua Owusu | Paid | $98.94 | |
| ORD-1043 | Ama Mensah | Paid | $135.91 | |
| ORD-1044 | Yaw Boateng | Pending | $172.88 | |
| ORD-1045 | Efua Asante | Paid | $29.85 | |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 | |
| ORD-1047 | Abena Darko | Pending | $103.79 | |
| ORD-1048 | Kwabena Osei | Paid | $140.76 | |
| ORD-1049 | Adjoa Frimpong | Paid | $177.73 | |
| ORD-1050 | Kojo Asante | Pending | $34.70 | |
| ORD-1051 | Akua Sarpong | Paid | $71.67 | |
| ORD-1052 | Yaa Amponsah | Paid | $108.64 | |
| ORD-1053 | Kwesi Appiah | Paid | $145.61 | |
| ORD-1054 | Afia Boadu | Pending | $182.58 | |
| ORD-1055 | Kwaku Antwi | Paid | $39.55 | |
| ORD-1056 | Esi Danso | Refunded | $76.52 | |
| ORD-1057 | Kofi Addo | Pending | $113.49 | |
| ORD-1058 | Akosua Owusu | Paid | $150.46 | |
| ORD-1059 | Ama Mensah | Paid | $187.43 | |
| ORD-1060 | Yaw Boateng | Pending | $44.40 | |
| ORD-1061 | Efua Asante | Paid | $81.37 | |
| ORD-1062 | Kwame Nkrumah Jr. | Paid | $118.34 | |
| ORD-1063 | Abena Darko | Paid | $155.31 | |
| ORD-1064 | Kwabena Osei | Pending | $192.28 | |
| ORD-1065 | Adjoa Frimpong | Paid | $49.25 | |
| ORD-1066 | Kojo Asante | Refunded | $86.22 | |
| ORD-1067 | Akua Sarpong | Pending | $123.19 | |
| ORD-1068 | Yaa Amponsah | Paid | $160.16 | |
| ORD-1069 | Kwesi Appiah | Paid | $197.13 | |
| ORD-1070 | Afia Boadu | Pending | $54.10 | |
| ORD-1071 | Kwaku Antwi | Paid | $91.07 | |
| ORD-1072 | Esi Danso | Paid | $128.04 | |
| ORD-1073 | Kofi Addo | Paid | $165.01 | |
| ORD-1074 | Akosua Owusu | Pending | $201.98 | |
| No records found. | ||||
Single Selection
Use selection-mode="single" for pick-one flows, choosing a reviewer to assign, picking a default address, selecting one plan.
| Select all rows | Reviewer | Department |
|---|---|---|
| Ama Mensah | Support | |
| Kofi Addo | Engineering | |
| Yaw Boateng | Finance | |
| No records found. | ||
Preselected Rows
Pass selected with an array of row keys to render the grid with some rows already checked, useful for an edit form that reopens with a saved set of chosen rows.
<x-bladewind::data-grid name="preselected-orders" label="Orders" selectable="true"
:selected="['3', '7', '12']"
:columns="$orderColumns" :rows="$orders" />
| Status | ||||
|---|---|---|---|---|
| ORD-1041 | Kofi Addo | Paid | $61.97 | |
| ORD-1042 | Akosua Owusu | Paid | $98.94 | |
| ORD-1043 | Ama Mensah | Paid | $135.91 | |
| ORD-1044 | Yaw Boateng | Pending | $172.88 | |
| ORD-1045 | Efua Asante | Paid | $29.85 | |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 | |
| ORD-1047 | Abena Darko | Pending | $103.79 | |
| ORD-1048 | Kwabena Osei | Paid | $140.76 | |
| ORD-1049 | Adjoa Frimpong | Paid | $177.73 | |
| ORD-1050 | Kojo Asante | Pending | $34.70 | |
| ORD-1051 | Akua Sarpong | Paid | $71.67 | |
| ORD-1052 | Yaa Amponsah | Paid | $108.64 | |
| ORD-1053 | Kwesi Appiah | Paid | $145.61 | |
| ORD-1054 | Afia Boadu | Pending | $182.58 | |
| ORD-1055 | Kwaku Antwi | Paid | $39.55 | |
| ORD-1056 | Esi Danso | Refunded | $76.52 | |
| ORD-1057 | Kofi Addo | Pending | $113.49 | |
| ORD-1058 | Akosua Owusu | Paid | $150.46 | |
| ORD-1059 | Ama Mensah | Paid | $187.43 | |
| ORD-1060 | Yaw Boateng | Pending | $44.40 | |
| ORD-1061 | Efua Asante | Paid | $81.37 | |
| ORD-1062 | Kwame Nkrumah Jr. | Paid | $118.34 | |
| ORD-1063 | Abena Darko | Paid | $155.31 | |
| ORD-1064 | Kwabena Osei | Pending | $192.28 | |
| ORD-1065 | Adjoa Frimpong | Paid | $49.25 | |
| ORD-1066 | Kojo Asante | Refunded | $86.22 | |
| ORD-1067 | Akua Sarpong | Pending | $123.19 | |
| ORD-1068 | Yaa Amponsah | Paid | $160.16 | |
| ORD-1069 | Kwesi Appiah | Paid | $197.13 | |
| ORD-1070 | Afia Boadu | Pending | $54.10 | |
| ORD-1071 | Kwaku Antwi | Paid | $91.07 | |
| ORD-1072 | Esi Danso | Paid | $128.04 | |
| ORD-1073 | Kofi Addo | Paid | $165.01 | |
| ORD-1074 | Akosua Owusu | Pending | $201.98 | |
| No records found. | ||||
Bulk Actions
The bulk-actions slot renders inside the selection bar, next to the clear-selection control, and only appears once at least one row is selected. Pair it with dataGridSelectedKeys() to read the current selection when a bulk action fires.
<x-bladewind::data-grid name="orders-with-actions" label="Orders" selectable="true"
:columns="$orderColumns" :rows="$orders">
<x-slot:bulk-actions>
<x-bladewind::button size="small" onclick="alert('Exporting: ' + dataGridSelectedKeys('orders-with-actions').join(', '))">Export</x-bladewind::button>
<x-bladewind::button size="small" type="red" onclick="alert('Deleting: ' + dataGridSelectedKeys('orders-with-actions').join(', '))">Delete</x-bladewind::button>
</x-slot:bulk-actions>
</x-bladewind::data-grid>
| Status | ||||
|---|---|---|---|---|
| ORD-1041 | Kofi Addo | Paid | $61.97 | |
| ORD-1042 | Akosua Owusu | Paid | $98.94 | |
| ORD-1043 | Ama Mensah | Paid | $135.91 | |
| ORD-1044 | Yaw Boateng | Pending | $172.88 | |
| ORD-1045 | Efua Asante | Paid | $29.85 | |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 | |
| ORD-1047 | Abena Darko | Pending | $103.79 | |
| ORD-1048 | Kwabena Osei | Paid | $140.76 | |
| ORD-1049 | Adjoa Frimpong | Paid | $177.73 | |
| ORD-1050 | Kojo Asante | Pending | $34.70 | |
| ORD-1051 | Akua Sarpong | Paid | $71.67 | |
| ORD-1052 | Yaa Amponsah | Paid | $108.64 | |
| ORD-1053 | Kwesi Appiah | Paid | $145.61 | |
| ORD-1054 | Afia Boadu | Pending | $182.58 | |
| ORD-1055 | Kwaku Antwi | Paid | $39.55 | |
| ORD-1056 | Esi Danso | Refunded | $76.52 | |
| ORD-1057 | Kofi Addo | Pending | $113.49 | |
| ORD-1058 | Akosua Owusu | Paid | $150.46 | |
| ORD-1059 | Ama Mensah | Paid | $187.43 | |
| ORD-1060 | Yaw Boateng | Pending | $44.40 | |
| ORD-1061 | Efua Asante | Paid | $81.37 | |
| ORD-1062 | Kwame Nkrumah Jr. | Paid | $118.34 | |
| ORD-1063 | Abena Darko | Paid | $155.31 | |
| ORD-1064 | Kwabena Osei | Pending | $192.28 | |
| ORD-1065 | Adjoa Frimpong | Paid | $49.25 | |
| ORD-1066 | Kojo Asante | Refunded | $86.22 | |
| ORD-1067 | Akua Sarpong | Pending | $123.19 | |
| ORD-1068 | Yaa Amponsah | Paid | $160.16 | |
| ORD-1069 | Kwesi Appiah | Paid | $197.13 | |
| ORD-1070 | Afia Boadu | Pending | $54.10 | |
| ORD-1071 | Kwaku Antwi | Paid | $91.07 | |
| ORD-1072 | Esi Danso | Paid | $128.04 | |
| ORD-1073 | Kofi Addo | Paid | $165.01 | |
| ORD-1074 | Akosua Owusu | Pending | $201.98 | |
| No records found. | ||||
Select a couple of rows above, then try the Export and Delete buttons that appear in the selection bar.
Pagination and Server-Driven State
Set paginated="true" with page-size for client-side pagination, as in the orders grid at the top of this page. The grid renders its own previous and next footer and keeps it in sync with sorting and searching, page one always reflects whatever the current sort and search produce.
Client-Side Pagination at Scale
Client pagination still ships every row to the browser and pages through them there, which is fine for a few hundred rows but the wrong tool once a dataset grows past what is reasonable to send on every page load. The grid below pages through the same 34-row order list at a smaller page size, six pages of six rows each, to show the previous and next controls disabling correctly at both ends.
| Status | |||
|---|---|---|---|
| ORD-1041 | Kofi Addo | Paid | $61.97 |
| ORD-1042 | Akosua Owusu | Paid | $98.94 |
| ORD-1043 | Ama Mensah | Paid | $135.91 |
| ORD-1044 | Yaw Boateng | Pending | $172.88 |
| ORD-1045 | Efua Asante | Paid | $29.85 |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 |
| ORD-1047 | Abena Darko | Pending | $103.79 |
| ORD-1048 | Kwabena Osei | Paid | $140.76 |
| ORD-1049 | Adjoa Frimpong | Paid | $177.73 |
| ORD-1050 | Kojo Asante | Pending | $34.70 |
| ORD-1051 | Akua Sarpong | Paid | $71.67 |
| ORD-1052 | Yaa Amponsah | Paid | $108.64 |
| ORD-1053 | Kwesi Appiah | Paid | $145.61 |
| ORD-1054 | Afia Boadu | Pending | $182.58 |
| ORD-1055 | Kwaku Antwi | Paid | $39.55 |
| ORD-1056 | Esi Danso | Refunded | $76.52 |
| ORD-1057 | Kofi Addo | Pending | $113.49 |
| ORD-1058 | Akosua Owusu | Paid | $150.46 |
| ORD-1059 | Ama Mensah | Paid | $187.43 |
| ORD-1060 | Yaw Boateng | Pending | $44.40 |
| ORD-1061 | Efua Asante | Paid | $81.37 |
| ORD-1062 | Kwame Nkrumah Jr. | Paid | $118.34 |
| ORD-1063 | Abena Darko | Paid | $155.31 |
| ORD-1064 | Kwabena Osei | Pending | $192.28 |
| ORD-1065 | Adjoa Frimpong | Paid | $49.25 |
| ORD-1066 | Kojo Asante | Refunded | $86.22 |
| ORD-1067 | Akua Sarpong | Pending | $123.19 |
| ORD-1068 | Yaa Amponsah | Paid | $160.16 |
| ORD-1069 | Kwesi Appiah | Paid | $197.13 |
| ORD-1070 | Afia Boadu | Pending | $54.10 |
| ORD-1071 | Kwaku Antwi | Paid | $91.07 |
| ORD-1072 | Esi Danso | Paid | $128.04 |
| ORD-1073 | Kofi Addo | Paid | $165.01 |
| ORD-1074 | Akosua Owusu | Pending | $201.98 |
| No records found. | |||
Server-Driven Pagination
Pass a real Laravel paginator through paginator instead of setting paginated directly, the grid detects it and switches into server mode on its own, rendering Pagination's standard page links. rows should be the paginator's current-page items, not the full dataset.
// in your controller or route closure
$staff = Staff::query()->orderBy('company_name')->paginate(8);
return view('staff.index', ['staff' => $staff]);
<x-bladewind::data-grid name="staff-directory" label="Staff directory" row-key="member_id"
:columns="[
['key' => 'company_name', 'label' => 'Company', 'sortable' => true],
['key' => 'first_name', 'label' => 'Contact', 'format' => fn ($v, $row) => $row['first_name'].' '.$row['last_name']],
['key' => 'mobile', 'label' => 'Mobile'],
['key' => 'email', 'label' => 'Email'],
]"
:rows="$staff->items()"
:paginator="$staff" />
| Contact | Mobile | ||
|---|---|---|---|
| Walter, Hilpert and Hermann | Larue Bailey | 1-754-852-3518 | brakus.roman@example.com |
| Ledner LLC | Tyra DuBuque | 1-732-800-2160 | opal.stark@example.com |
| Strosin-Dietrich | Michele Jones | +16014555530 | wolff.laurine@example.net |
| Cassin-Wisoky | Norris Bartoletti | +1-838-240-3720 | zchamplin@example.org |
| Kerluke, Cummerata and Harvey | Elaina Jakubowski | (732) 660-6750 | bergstrom.kennedi@example.com |
| Schowalter Ltd | Keon Gaylord | +1.979.913.2605 | alexa82@example.net |
| Haag, Hill and King | Alec Kulas | 283-938-7998 | ssatterfield@example.net |
| Abbott-Bruen | Rocky Gorczany | 843.877.7252 | jratke@example.org |
| No records found. | |||
This one is not a simulation. The 222-record directory behind it lives in a plain PHP file on the server, and the page links above genuinely reload the page with a real, different set of 8 records each time, exactly what a database-backed grid would do.
sortable and searchable client-side behaviour for the same reason client pagination does not apply here: the rows in the DOM are only ever one page's worth. Wire header clicks and the search field to your query string or an event listener instead, the same pattern shown under server-driven sorting and server-driven searching above.Loading State
Set loading="true", or call setDataGridLoading(name, true), while an application fetches new rows for a server-driven grid. The table dims and shows a progress indicator, and screen readers see aria-busy="true".
| Status | |||
|---|---|---|---|
| ORD-1041 | Kofi Addo | Paid | $61.97 |
| ORD-1042 | Akosua Owusu | Paid | $98.94 |
| ORD-1043 | Ama Mensah | Paid | $135.91 |
| ORD-1044 | Yaw Boateng | Pending | $172.88 |
| ORD-1045 | Efua Asante | Paid | $29.85 |
| No records found. | |||
Appearance
striped, bordered, and dense control visual density. sticky keeps the header pinned while the body scrolls, and defaults to true. Set height to cap the grid at a fixed height with an internal scrollbar rather than letting it grow with the row count.
Striped
| Status | |||
|---|---|---|---|
| ORD-1041 | Kofi Addo | Paid | $61.97 |
| ORD-1042 | Akosua Owusu | Paid | $98.94 |
| ORD-1043 | Ama Mensah | Paid | $135.91 |
| ORD-1044 | Yaw Boateng | Pending | $172.88 |
| ORD-1045 | Efua Asante | Paid | $29.85 |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 |
| No records found. | |||
<x-bladewind::data-grid name="striped-grid" label="Orders" striped="true" :columns="$orderColumns" :rows="$orders" />
Bordered
| Status | |||
|---|---|---|---|
| ORD-1041 | Kofi Addo | Paid | $61.97 |
| ORD-1042 | Akosua Owusu | Paid | $98.94 |
| ORD-1043 | Ama Mensah | Paid | $135.91 |
| ORD-1044 | Yaw Boateng | Pending | $172.88 |
| ORD-1045 | Efua Asante | Paid | $29.85 |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 |
| No records found. | |||
<x-bladewind::data-grid name="bordered-grid" label="Orders" bordered="true" :columns="$orderColumns" :rows="$orders" />
Sticky Header
sticky pins the header row while the body scrolls, and defaults to true. It only has something to do once the grid has a height short enough that the rows actually scroll, so the two go together. Scroll inside the grid below and the header stays put.
| Status | |||
|---|---|---|---|
| ORD-1041 | Kofi Addo | Paid | $61.97 |
| ORD-1042 | Akosua Owusu | Paid | $98.94 |
| ORD-1043 | Ama Mensah | Paid | $135.91 |
| ORD-1044 | Yaw Boateng | Pending | $172.88 |
| ORD-1045 | Efua Asante | Paid | $29.85 |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 |
| ORD-1047 | Abena Darko | Pending | $103.79 |
| ORD-1048 | Kwabena Osei | Paid | $140.76 |
| ORD-1049 | Adjoa Frimpong | Paid | $177.73 |
| ORD-1050 | Kojo Asante | Pending | $34.70 |
| ORD-1051 | Akua Sarpong | Paid | $71.67 |
| ORD-1052 | Yaa Amponsah | Paid | $108.64 |
| ORD-1053 | Kwesi Appiah | Paid | $145.61 |
| ORD-1054 | Afia Boadu | Pending | $182.58 |
| ORD-1055 | Kwaku Antwi | Paid | $39.55 |
| ORD-1056 | Esi Danso | Refunded | $76.52 |
| ORD-1057 | Kofi Addo | Pending | $113.49 |
| ORD-1058 | Akosua Owusu | Paid | $150.46 |
| ORD-1059 | Ama Mensah | Paid | $187.43 |
| ORD-1060 | Yaw Boateng | Pending | $44.40 |
| ORD-1061 | Efua Asante | Paid | $81.37 |
| ORD-1062 | Kwame Nkrumah Jr. | Paid | $118.34 |
| ORD-1063 | Abena Darko | Paid | $155.31 |
| ORD-1064 | Kwabena Osei | Pending | $192.28 |
| ORD-1065 | Adjoa Frimpong | Paid | $49.25 |
| ORD-1066 | Kojo Asante | Refunded | $86.22 |
| ORD-1067 | Akua Sarpong | Pending | $123.19 |
| ORD-1068 | Yaa Amponsah | Paid | $160.16 |
| ORD-1069 | Kwesi Appiah | Paid | $197.13 |
| ORD-1070 | Afia Boadu | Pending | $54.10 |
| ORD-1071 | Kwaku Antwi | Paid | $91.07 |
| ORD-1072 | Esi Danso | Paid | $128.04 |
| ORD-1073 | Kofi Addo | Paid | $165.01 |
| ORD-1074 | Akosua Owusu | Pending | $201.98 |
| No records found. | |||
<x-bladewind::data-grid name="sticky-grid" label="Orders" height="12rem" :columns="$orderColumns" :rows="$orders" />
Set sticky="false" to let the header scroll away with the rest of the content instead, useful if the grid already sits inside its own scroll container that provides a sticky header at a higher level.
| Status | |||
|---|---|---|---|
| ORD-1041 | Kofi Addo | Paid | $61.97 |
| ORD-1042 | Akosua Owusu | Paid | $98.94 |
| ORD-1043 | Ama Mensah | Paid | $135.91 |
| ORD-1044 | Yaw Boateng | Pending | $172.88 |
| ORD-1045 | Efua Asante | Paid | $29.85 |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 |
| ORD-1047 | Abena Darko | Pending | $103.79 |
| ORD-1048 | Kwabena Osei | Paid | $140.76 |
| ORD-1049 | Adjoa Frimpong | Paid | $177.73 |
| ORD-1050 | Kojo Asante | Pending | $34.70 |
| ORD-1051 | Akua Sarpong | Paid | $71.67 |
| ORD-1052 | Yaa Amponsah | Paid | $108.64 |
| ORD-1053 | Kwesi Appiah | Paid | $145.61 |
| ORD-1054 | Afia Boadu | Pending | $182.58 |
| ORD-1055 | Kwaku Antwi | Paid | $39.55 |
| ORD-1056 | Esi Danso | Refunded | $76.52 |
| ORD-1057 | Kofi Addo | Pending | $113.49 |
| ORD-1058 | Akosua Owusu | Paid | $150.46 |
| ORD-1059 | Ama Mensah | Paid | $187.43 |
| ORD-1060 | Yaw Boateng | Pending | $44.40 |
| ORD-1061 | Efua Asante | Paid | $81.37 |
| ORD-1062 | Kwame Nkrumah Jr. | Paid | $118.34 |
| ORD-1063 | Abena Darko | Paid | $155.31 |
| ORD-1064 | Kwabena Osei | Pending | $192.28 |
| ORD-1065 | Adjoa Frimpong | Paid | $49.25 |
| ORD-1066 | Kojo Asante | Refunded | $86.22 |
| ORD-1067 | Akua Sarpong | Pending | $123.19 |
| ORD-1068 | Yaa Amponsah | Paid | $160.16 |
| ORD-1069 | Kwesi Appiah | Paid | $197.13 |
| ORD-1070 | Afia Boadu | Pending | $54.10 |
| ORD-1071 | Kwaku Antwi | Paid | $91.07 |
| ORD-1072 | Esi Danso | Paid | $128.04 |
| ORD-1073 | Kofi Addo | Paid | $165.01 |
| ORD-1074 | Akosua Owusu | Pending | $201.98 |
| No records found. | |||
<x-bladewind::data-grid name="non-sticky-grid" label="Orders" height="12rem" sticky="false" :columns="$orderColumns" :rows="$orders" />
Dense, With a Fixed Scrollable Height
dense and a fixed height pair well for a compact grid embedded inside a card or a dashboard widget, where the header should stay visible while the body scrolls internally instead of pushing the rest of the page down.
| Status | |||
|---|---|---|---|
| ORD-1041 | Kofi Addo | Paid | $61.97 |
| ORD-1042 | Akosua Owusu | Paid | $98.94 |
| ORD-1043 | Ama Mensah | Paid | $135.91 |
| ORD-1044 | Yaw Boateng | Pending | $172.88 |
| ORD-1045 | Efua Asante | Paid | $29.85 |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 |
| ORD-1047 | Abena Darko | Pending | $103.79 |
| ORD-1048 | Kwabena Osei | Paid | $140.76 |
| ORD-1049 | Adjoa Frimpong | Paid | $177.73 |
| ORD-1050 | Kojo Asante | Pending | $34.70 |
| ORD-1051 | Akua Sarpong | Paid | $71.67 |
| ORD-1052 | Yaa Amponsah | Paid | $108.64 |
| ORD-1053 | Kwesi Appiah | Paid | $145.61 |
| ORD-1054 | Afia Boadu | Pending | $182.58 |
| ORD-1055 | Kwaku Antwi | Paid | $39.55 |
| ORD-1056 | Esi Danso | Refunded | $76.52 |
| ORD-1057 | Kofi Addo | Pending | $113.49 |
| ORD-1058 | Akosua Owusu | Paid | $150.46 |
| ORD-1059 | Ama Mensah | Paid | $187.43 |
| ORD-1060 | Yaw Boateng | Pending | $44.40 |
| ORD-1061 | Efua Asante | Paid | $81.37 |
| ORD-1062 | Kwame Nkrumah Jr. | Paid | $118.34 |
| ORD-1063 | Abena Darko | Paid | $155.31 |
| ORD-1064 | Kwabena Osei | Pending | $192.28 |
| ORD-1065 | Adjoa Frimpong | Paid | $49.25 |
| ORD-1066 | Kojo Asante | Refunded | $86.22 |
| ORD-1067 | Akua Sarpong | Pending | $123.19 |
| ORD-1068 | Yaa Amponsah | Paid | $160.16 |
| ORD-1069 | Kwesi Appiah | Paid | $197.13 |
| ORD-1070 | Afia Boadu | Pending | $54.10 |
| ORD-1071 | Kwaku Antwi | Paid | $91.07 |
| ORD-1072 | Esi Danso | Paid | $128.04 |
| ORD-1073 | Kofi Addo | Paid | $165.01 |
| ORD-1074 | Akosua Owusu | Pending | $201.98 |
| No records found. | |||
<x-bladewind::data-grid name="dense-grid" label="Compact orders"
striped="true" dense="true" height="14rem"
:columns="$orderColumns" :rows="$orders" />
Toolbar
The toolbar slot renders next to the search field, for controls that apply to the grid as a whole rather than to a selection, an export button, a view switcher, a status filter.
<x-bladewind::data-grid name="orders-with-toolbar" label="Orders" searchable="true"
:columns="$orderColumns" :rows="$orders">
<x-slot:toolbar>
<x-bladewind::button size="small" onclick="alert('Exporting all orders as CSV')">Export CSV</x-bladewind::button>
</x-slot:toolbar>
</x-bladewind::data-grid>
| Status | |||
|---|---|---|---|
| ORD-1041 | Kofi Addo | Paid | $61.97 |
| ORD-1042 | Akosua Owusu | Paid | $98.94 |
| ORD-1043 | Ama Mensah | Paid | $135.91 |
| ORD-1044 | Yaw Boateng | Pending | $172.88 |
| ORD-1045 | Efua Asante | Paid | $29.85 |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 |
| ORD-1047 | Abena Darko | Pending | $103.79 |
| ORD-1048 | Kwabena Osei | Paid | $140.76 |
| ORD-1049 | Adjoa Frimpong | Paid | $177.73 |
| ORD-1050 | Kojo Asante | Pending | $34.70 |
| ORD-1051 | Akua Sarpong | Paid | $71.67 |
| ORD-1052 | Yaa Amponsah | Paid | $108.64 |
| ORD-1053 | Kwesi Appiah | Paid | $145.61 |
| ORD-1054 | Afia Boadu | Pending | $182.58 |
| ORD-1055 | Kwaku Antwi | Paid | $39.55 |
| ORD-1056 | Esi Danso | Refunded | $76.52 |
| ORD-1057 | Kofi Addo | Pending | $113.49 |
| ORD-1058 | Akosua Owusu | Paid | $150.46 |
| ORD-1059 | Ama Mensah | Paid | $187.43 |
| ORD-1060 | Yaw Boateng | Pending | $44.40 |
| ORD-1061 | Efua Asante | Paid | $81.37 |
| ORD-1062 | Kwame Nkrumah Jr. | Paid | $118.34 |
| ORD-1063 | Abena Darko | Paid | $155.31 |
| ORD-1064 | Kwabena Osei | Pending | $192.28 |
| ORD-1065 | Adjoa Frimpong | Paid | $49.25 |
| ORD-1066 | Kojo Asante | Refunded | $86.22 |
| ORD-1067 | Akua Sarpong | Pending | $123.19 |
| ORD-1068 | Yaa Amponsah | Paid | $160.16 |
| ORD-1069 | Kwesi Appiah | Paid | $197.13 |
| ORD-1070 | Afia Boadu | Pending | $54.10 |
| ORD-1071 | Kwaku Antwi | Paid | $91.07 |
| ORD-1072 | Esi Danso | Paid | $128.04 |
| ORD-1073 | Kofi Addo | Paid | $165.01 |
| ORD-1074 | Akosua Owusu | Pending | $201.98 |
| No records found. | |||
Custom Layout
Skip columns and rows entirely for a fully custom layout: a header slot for <th> content, and the default slot for hand-written <tr> rows. This is the escape hatch for a table body that does not fit the column model at all, merged cells, a summary row, a layout the grid was never meant to describe.
columns and rows the grid normalises internally. You are responsible for reimplementing any of that behaviour yourself against your hand-written markup.<x-bladewind::data-grid name="custom-orders" label="Orders summary">
<x-slot:header>
<th>Reference</th>
<th>Customer</th>
<th class="text-right">Total</th>
</x-slot:header>
<tr>
<td>ORD-1041</td>
<td>Kofi Addo</td>
<td class="text-right">$84.00</td>
</tr>
<tr class="font-semibold">
<td colspan="2">Total</td>
<td class="text-right">$84.00</td>
</tr>
</x-bladewind::data-grid>
| Reference | Customer | Total |
|---|---|---|
| ORD-1041 | Kofi Addo | $84.00 |
| Total | $84.00 | |
Events
Before events are cancelable. Call preventDefault() on the event to stop the related change, useful for confirming a destructive selection change or blocking a sort while a save is in flight. All event names start with bladewind:data-grid:.
| Event suffix | When it runs |
|---|---|
before-sort-change, sort-change | Before and after a column's sort state changes. |
before-select-change, select-change | Before and after row selection changes. Preventing the before event reverts the checkbox or radio. |
before-page-change, page-change | Before and after the current client page changes. |
search | On every keystroke in the search field, with the current query. |
A practical use for the before events is confirming a change rather than silently accepting it:
document.addEventListener('bladewind:data-grid:before-select-change', (event) => {
if (event.detail.name !== 'orders-grid') return;
if (event.detail.selecting && event.detail.row.status === 'refunded') {
if (!confirm('This order was refunded. Select it anyway?')) {
event.preventDefault();
}
}
});
Full List of Attributes
| Attribute | Default | Description |
|---|---|---|
| name | Generated | Unique public helper and DOM scope. |
| label | Data grid | Accessible table name. |
| columns | [] | Column model. Omit with rows for a custom layout. |
| rows | null | Array of associative arrays or objects to render. |
| row-key | id | Field used as each row's unique identity. |
| selectable | false | Adds a selection column. |
| selection-mode | multiple | multiple (checkboxes) or single (radios). |
| selected | [] | Row keys to preselect. |
| sortable | false | Makes every column sortable. A column's own sortable key wins per column. |
| sort-key | null | Column key to render as initially sorted. |
| sort-direction | null | asc or desc, paired with sort-key. |
| client-sort | true | Reorders rows in the browser. When false, only the indicator updates and the app must reorder the data. |
| searchable | false | Renders the toolbar search field. |
| search-placeholder | Search… | Search field placeholder text. |
| client-search | true | Filters rows in the browser. When false, only the search event fires. |
| paginated | false | Enables client pagination. Implied automatically by passing paginator. |
| page-size | 25 | Rows per page in client pagination mode. |
| paginator | null | A Laravel paginator, for server-driven pagination. |
| sticky | true | Pins the header while the body scrolls. |
| loading | false | Dims the table and shows a progress indicator. |
| empty-text | No records found. | Text shown when there are no rows. |
| striped | false | Alternating row background. |
| bordered | false | Vertical cell borders. |
| dense | false | Reduced cell padding. |
| height | null | Max height for the scrollable body, e.g. 24rem. |
| select-all-label | Select all rows | Accessible label for the header checkbox. |
| clear-selection-label | Clear selection | Label for the clear-selection control. |
Slots
| Slot | Description |
|---|---|
| toolbar | Content appended after the search field. See Toolbar. |
| bulk-actions | Custom buttons in the selection bar. See Bulk actions. |
| header | Custom <th> content, used instead of columns. See Custom layout. |
| default | Custom <tr> rows, used instead of rows. See Custom layout. |
JavaScript API
Every helper returns true when it completes, or when the requested state already applies, and false when the target is missing or a cancelable event was prevented.
| Function | What it does |
|---|---|
sortDataGrid(name, key, direction) | Sorts a client-mode grid by the given column, direction is 'asc', 'desc', or null to clear. |
setDataGridPage(name, page) | Jumps to a page in a client-paginated grid. |
selectAllDataGridRows(name, selected) | Selects or deselects every visible row, matching the header checkbox. |
clearDataGridSelection(name) | Clears the current selection entirely. |
dataGridSelectedKeys(name) | Returns an array of the currently selected row keys. |
setDataGridLoading(name, loading) | Toggles the dimmed, busy loading state. See Loading state. |
resetDataGrid(name) | Clears search, sort, selection, and returns to page one, all at once. |
sortDataGrid('orders-grid', 'total', 'desc');
setDataGridPage('orders-grid', 2);
selectAllDataGridRows('orders-grid', true);
dataGridSelectedKeys('orders-grid'); // ['3', '7', '12']
clearDataGridSelection('orders-grid');
setDataGridLoading('orders-grid', true);
resetDataGrid('orders-grid');
Putting It All Together
A grid combining most of what is documented above: searchable, multi-select with bulk actions, a toolbar export button, striped rows, and client pagination over the full 34-row order list.
<x-bladewind::data-grid name="complete-orders" label="Orders" row-key="reference"
searchable="true" search-placeholder="Search orders…"
selectable="true" selection-mode="multiple"
sortable="true" striped="true"
paginated="true" page-size="10"
:columns="$orderColumns" :rows="$orders">
<x-slot:toolbar>
<x-bladewind::button size="small">Export CSV</x-bladewind::button>
</x-slot:toolbar>
<x-slot:bulk-actions>
<x-bladewind::button size="small" type="red">Delete selected</x-bladewind::button>
</x-slot:bulk-actions>
</x-bladewind::data-grid>
| ORD-1041 | Kofi Addo | Paid | $61.97 | |
| ORD-1042 | Akosua Owusu | Paid | $98.94 | |
| ORD-1043 | Ama Mensah | Paid | $135.91 | |
| ORD-1044 | Yaw Boateng | Pending | $172.88 | |
| ORD-1045 | Efua Asante | Paid | $29.85 | |
| ORD-1046 | Kwame Nkrumah Jr. | Refunded | $66.82 | |
| ORD-1047 | Abena Darko | Pending | $103.79 | |
| ORD-1048 | Kwabena Osei | Paid | $140.76 | |
| ORD-1049 | Adjoa Frimpong | Paid | $177.73 | |
| ORD-1050 | Kojo Asante | Pending | $34.70 | |
| ORD-1051 | Akua Sarpong | Paid | $71.67 | |
| ORD-1052 | Yaa Amponsah | Paid | $108.64 | |
| ORD-1053 | Kwesi Appiah | Paid | $145.61 | |
| ORD-1054 | Afia Boadu | Pending | $182.58 | |
| ORD-1055 | Kwaku Antwi | Paid | $39.55 | |
| ORD-1056 | Esi Danso | Refunded | $76.52 | |
| ORD-1057 | Kofi Addo | Pending | $113.49 | |
| ORD-1058 | Akosua Owusu | Paid | $150.46 | |
| ORD-1059 | Ama Mensah | Paid | $187.43 | |
| ORD-1060 | Yaw Boateng | Pending | $44.40 | |
| ORD-1061 | Efua Asante | Paid | $81.37 | |
| ORD-1062 | Kwame Nkrumah Jr. | Paid | $118.34 | |
| ORD-1063 | Abena Darko | Paid | $155.31 | |
| ORD-1064 | Kwabena Osei | Pending | $192.28 | |
| ORD-1065 | Adjoa Frimpong | Paid | $49.25 | |
| ORD-1066 | Kojo Asante | Refunded | $86.22 | |
| ORD-1067 | Akua Sarpong | Pending | $123.19 | |
| ORD-1068 | Yaa Amponsah | Paid | $160.16 | |
| ORD-1069 | Kwesi Appiah | Paid | $197.13 | |
| ORD-1070 | Afia Boadu | Pending | $54.10 | |
| ORD-1071 | Kwaku Antwi | Paid | $91.07 | |
| ORD-1072 | Esi Danso | Paid | $128.04 | |
| ORD-1073 | Kofi Addo | Paid | $165.01 | |
| ORD-1074 | Akosua Owusu | Pending | $201.98 | |
| No records found. | ||||
resources > views > components > bladewind > data-grid