title | weight |
---|---|
Secondary Header |
6 |
A secondary header is a body table row underneath the thead
that can serve whatever purpose you need. It is passed the current rows of the table at the time so you can use it to tally numbers or show messages based on those rows.
Here is you how define a secondary header for a column:
Column::make('Price')
->sortable()
->secondaryHeader(function($rows) {
return 'Subtotal: ' . $rows->sum('price');
}),
The secondary header row is enabled when ever any column calls secondaryHeader
.
See also secondary header component configuration.
Column search is not built in by default, but is easily achievable using this feature.
Here are the steps you need to take:
- Add state to the component to track the input values
- Add the inputs to the columns using the secondaryHeader method
- Add the clause to the query based on the new state
- Optionally, add the state to the query string to preserve it on page load.
This can be called whatever you want, but you need an array to house the values of the column search fields:
public $columnSearch = [
'name' => null,
];
You can do this inline, but I'll break it out into a partial for clarity:
Column::make('Name')
->sortable()
->searchable()
->asHtml()
->secondaryHeader(function() {
return view('tables.cells.input-search', ['field' => 'name']);
}),
input-search.blade.php
<input type="text" wire:model.debounce="columnSearch.{{ $field }}" placeholder="Search {{ ucfirst($field) }}" class="block w-full border-gray-300 rounded-md shadow-sm transition duration-150 ease-in-out sm:text-sm sm:leading-5 dark:bg-gray-700 dark:text-white dark:border-gray-600 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md" />
Now you need to tell the query what to do when something is typed into the search:
public function query()
{
return User::query()
->when($this->columnSearch['name'] ?? null, fn ($query, $name) => $query->where('name', 'like', '%' . $name . '%'));
}
If you want the input to have a clear button when it has a value like the default search does:
- Send the state to the partial
Column::make('Name')
->sortable()
->searchable()
->asHtml()
->secondaryHeader(function() {
return view('tables.cells.input-search', ['field' => 'name', 'columnSearch' => $this->columnSearch]);
}),
- Copy the search field and modify:
<div class="flex rounded-md shadow-sm">
<input
wire:model.debounce="columnSearch.{{ $field }}"
placeholder="Search {{ ucfirst($field) }}"
type="text"
class="block w-full border-gray-300 rounded-md shadow-sm transition duration-150 ease-in-out sm:text-sm sm:leading-5 dark:bg-gray-700 dark:text-white dark:border-gray-600 @if (isset($columnSearch[$field]) && strlen($columnSearch[$field])) rounded-none rounded-l-md focus:ring-0 focus:border-gray-300 @else focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md @endif"
/>
@if (isset($columnSearch[$field]) && strlen($columnSearch[$field]))
<span wire:click="$set('columnSearch.{{ $field }}', null)" class="inline-flex items-center px-3 text-gray-500 bg-gray-50 rounded-r-md border border-l-0 border-gray-300 cursor-pointer sm:text-sm dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:hover:bg-gray-600">
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</span>
@endif
</div>