List Search
The search functionality allows users to filter list data by typing in a search field. The search is automatically applied via Global Scopes when the model uses the HasListScopes trait.
Enabling/Disabling the Search Field
In the YAML configuration, use disableSearch to control the search field visibility:
title: Customers
disableSearch: false # Search is enabled (default)
columns:
- field: name
label: Name
To disable the search field:
disableSearch: true
How Search Works
- The
NoerdListtrait provides a$searchproperty bound to the search input viawire:model.live="search" - When the user types,
updatedSearch()syncs the search value toListQueryContext - The
SearchScope(Global Scope) automatically reads fromListQueryContextand applies the filter - The model's
$searchableproperty defines which fields are searched
Setting Up Search in a Model
Add the HasListScopes trait and define the $searchable property:
<?php
namespace Nywerk\Customer\Models;
use Illuminate\Database\Eloquent\Model;
use Noerd\Traits\HasListScopes;
class Customer extends Model
{
use HasListScopes;
/**
* Fields that are searchable via the search scope.
*/
protected array $searchable = [
'name',
'company_name',
'email',
'zipcode',
];
}
Complete List Component Example
With HasListScopes and $searchable configured in the model, the list component is minimal:
<?php
use Livewire\Component;
use Noerd\Traits\NoerdList;
use Nywerk\Customer\Models\Customer;
new class extends Component {
use NoerdList;
public function listAction(mixed $modelId = null, array $relations = []): void
{
$this->dispatch(
event: 'noerdModal',
modalComponent: 'customer-detail',
source: $this->getComponentName(),
arguments: ['modelId' => $modelId, 'relations' => $relations],
);
}
public function with()
{
$rows = Customer::paginate(self::PAGINATION);
return [
'listConfig' => $this->buildList($rows),
];
}
}; ?>
<x-noerd::page :disableModal="$disableModal">
<x-noerd::list />
</x-noerd::page>
No manual search logic is needed in with() - the SearchScope handles it automatically.
Architecture Overview
User types in search field
↓
wire:model.live="search" updates $this->search
↓
updatedSearch() syncs to ListQueryContext
↓
Model query executes (e.g., Customer::paginate())
↓
SearchScope (Global Scope) reads from ListQueryContext
↓
SearchScope applies WHERE conditions based on $searchable
↓
Filtered results returned
The HasListScopes Trait
The trait provides:
- Global Scopes: Automatically registers
SearchScopeandSortScope getSearchableFields(): Returns the$searchablearrayscopeSearch(): Manual scope for backward compatibilityscopeSorted(): Manual scope for sorting
trait HasListScopes
{
public static function bootHasListScopes(): void
{
static::addGlobalScope(new SearchScope());
static::addGlobalScope(new SortScope());
}
public function getSearchableFields(): array
{
return $this->searchable ?? [];
}
}
Manual Search (Fallback)
For models without HasListScopes or for custom search logic, use the manual approach:
public function with()
{
$rows = SomeModel::query()
->when($this->search, function ($query): void {
$query->where(function ($query): void {
$query->where('name', 'like', '%' . $this->search . '%')
->orWhere('description', 'like', '%' . $this->search . '%');
});
})
->paginate(self::PAGINATION);
return [
'listConfig' => $this->buildList($rows),
];
}
Default Sorting
To set a default sort order for a list, use the setDefaultSort() method in your mount() method:
public function mount(): void
{
$this->mountList();
$this->setDefaultSort('invoice_date', false); // Sort by invoice_date descending
}
The method signature is:
protected function setDefaultSort(string $field, bool $ascending = false): void
$field: The column name to sort by$ascending:truefor ascending (A-Z, oldest first),falsefor descending (Z-A, newest first)
The method automatically syncs the sort state to ListQueryContext, ensuring the SortScope applies the correct ordering.
Best Practices
-
Use
HasListScopes: Prefer the automatic approach via the trait and$searchableproperty -
Choose searchable fields wisely: Only include fields users would expect to search
-
Consider performance: For large datasets, add database indexes on searchable columns
-
Keep it simple: The automatic approach keeps list components clean and consistent
Related Documentation
- List View - Basic list configuration
- List Filters - Dropdown filters for lists