Installation:
composer require beholdr/filament-trilist
For Filament 5.x, ensure version ^1.1.x is used.
Publish Views (Optional):
php artisan vendor:publish --tag="filament-trilist-views"
Only needed if customizing Blade templates.
First Use Case:
use Beholdr\FilamentTrilist\Forms\Components\TreeSelect;
TreeSelect::make('parent_id')
->label('Select Parent')
->options($this->getTreeData())
->required(),
use Beholdr\FilamentTrilist\Resources\Pages\TreeViewPage;
public static function getPages(): array
{
return [
TreeViewPage::route('/tree'),
];
}
Data Format: Ensure your data follows the required structure:
[
['id' => 1, 'label' => 'Root', 'children' => [...]],
// ...
]
Use staudenmeir/eloquent-eager-trees or similar for Eloquent models.
Basic Usage:
TreeSelect::make('category_id')
->options($categories->toTree())
->searchable()
->preload(),
searchable(): Adds a search input.preload(): Loads children on initial render (useful for large trees).Dynamic Data: Fetch data via a query method:
TreeSelect::make('parent_id')
->options(fn () => $this->getTreeData())
->rules(['required']),
Customizing Labels:
TreeSelect::make('parent_id')
->label('Parent Category')
->placeholder('Select a category...'),
Basic Setup:
TreeViewPage::make('categories')
->header('Category Tree')
->columns(3) // Adjust layout
->options($categories->toTree()),
columns(): Controls the number of columns in the tree view.Custom Actions: Add buttons or actions to tree nodes:
TreeViewPage::make('posts')
->actions([
TreeViewAction::make('edit')
->label('Edit')
->url(fn ($record) => route('admin.posts.edit', $record)),
]),
Eloquent Models:
Use staudenmeir/eloquent-eager-trees for Eloquent models:
use Staudenmeir\EloquentEagerTree\Tree;
class Category extends Model implements Tree
{
use \Staudenmeir\EloquentEagerTree\HasTree;
}
Then fetch data:
$categories = Category::with('children')->get()->toTree();
Custom Data Sources: For non-Eloquent data (e.g., API responses), transform to the required format:
$treeData = array_map(fn ($item) => [
'id' => $item['id'],
'label' => $item['name'],
'children' => $item['children'] ?? [],
], $apiResponse);
TreeSelect in Resource Forms:
// app/Filament/Resources/CategoryResource.php
public static function form(Form $form): Form
{
return $form
->schema([
TreeSelect::make('parent_id')
->options(fn () => Category::query()->toTree())
->required(false),
]);
}
TreeView as a Resource Page:
// app/Filament/Resources/CategoryResource/Pages/ManageCategories.php
public static function getPages(): array
{
return [
TreeViewPage::route('/tree-view'),
];
}
Custom CSS:
Publish views and override Blade templates (e.g., resources/views/vendor/filament-trilist/...).
Example: Modify tree-select.blade.php to change colors or icons.
Tailwind Classes: Use Tailwind classes directly in the component:
TreeSelect::make('parent_id')
->class('bg-gray-50 border-gray-300')
->searchable(),
id, label, children).$treeData = collect($rawData)->map(function ($item) {
return [
'id' => $item['id'] ?? null,
'label' => $item['name'] ?? 'Untitled',
'children' => $item['children'] ?? [],
];
})->toArray();
preload() to lazy-load children.maxDepth():
TreeSelect::make('parent_id')
->options($treeData)
->maxDepth(3),
staudenmeir/eloquent-eager-trees with with('children') and validate your model relationships.$treeData = Cache::remember('tree-data', now()->addHours(1), function () {
return Category::query()->toTree();
});
composer require beholdr/filament-trilist:^1.1.x # For Filament 5.x
TreeViewPage::make('categories')
->options($treeData)
->icon(fn ($item) => $item['is_root'] ? 'heroicon-o-home' : 'heroicon-o-folder'),
TreeSelect::make('parent_id')
->searchable()
->debounce(300), // 300ms delay
TreeSelect::make('parent_id')
->options($treeData)
->disabled(fn ($item) => $item['id'] === 1), // Disable root
TreeSelect::make('parent_id')
->label(__('filament-trilist::messages.select_parent'))
->placeholder(__('filament-trilist::messages.search_or_select')),
Publish translations:
php artisan vendor:publish --tag="filament-trilist-lang"
Custom Actions: Add buttons to TreeView nodes:
TreeViewPage::make('posts')
->actions([
TreeViewAction::make('delete')
->label('Delete')
->icon('heroicon-o-trash')
->action(fn ($record) => $this->delete($record)),
]),
Event Listeners: Listen to tree interactions:
TreeSelect::make('parent_id')
->options($treeData)
->listen('selected', fn ($value) => Log::info("Selected: {$value}")),
public function test_tree_select()
{
$component = TreeSelect::make('parent_id')
->options($treeData);
$this->filament()->actingAs($user)
->from('admin.resources.categories.edit')
->select($component)
->assertHasNoFormErrors();
}
How can I help you explore Laravel packages today?