A Filament package to manage adjacency lists (aka trees).
You can install the package via composer:
composer require saade/filament-adjacency-list
use Saade\FilamentAdjacencyList\Forms\Components\AdjacencyList; AdjacencyList::make('subjects') ->form([ Forms\Components\TextInput::make('label') ->required(), ])
label
key used to display the item's labelAdjacencyList::make('subjects') ->labelKey('name') // defaults to 'label'
children
key used to gather the item's children.Note: This is only used when not using relationships.
AdjacencyList::make('subjects') ->childrenKey('children') // defaults to 'children'
MaxDepth
of the tree.AdjacencyList::make('subjects') ->maxDepth(2) // defaults to -1 (unlimited depth)
AdjacencyList::make('subjects') ->modal(false) // defaults to true
AdjacencyList::make('subjects') ->addable(false) ->editable(false) ->deletable(false) ->reorderable(false)
use Filament\Forms\Actions\Action; AdjacencyList::make('subjects') ->addAction(fn (Action $action): Action => $action->icon('heroicon-o-plus')->color('primary')) ->addChildAction(fn (Action $action): Action => $action->button()) ->editAction(fn (Action $action): Action => $action->icon('heroicon-o-pencil')) ->deleteAction(fn (Action $action): Action => $action->requiresConfirmation()) ->reorderAction(fn (Action $action): Action => $action->icon('heroicon-o-arrow-path-rounded-square'))
❗ Important: Reorder Action
If you want to add
->extraAttributes()
to the action, you need to add the'data-sortable-handle' => 'true'
to the array, as the action serves as a handle for SortableJS.By default, clicking on the action will do anything. If you want to trigger some action on click, you need to chain
->livewireClickHandlerEnabled()
on the action.
In this example, we'll be creating a Ticketing system, where tickets can be assigned to a department, and departments have subjects.
// App/Models/Department.php class Department extends Model{ public function subjects(): HasMany { return $this->hasMany(Subject::class)->whereNull('parent_id')->with('children')->orderBy('sort'); }}
// App/Models/Subject.php class Subject extends Model{ protected $fillable ['parent_id', 'name', 'sort']; // or whatever your columns are public function children(): HasMany { return $this->hasMany(Subject::class, 'parent_id')->with('children')->orderBy('sort'); }}
Now you've created a nested relationship between departments and subjects.
// App/Filament/Resources/DepartmentResource.php AdjacencyList::make('subjects') ->relationship('subjects') // Define the relationship ->labelKey('name') // Customize the label key to your model's column ->childrenKey('children') // Customize the children key to the relationship's method name ->form([ // Define the form Forms\Components\TextInput::make('name') ->label(__('Name')) ->required(), ]);
That's it! Now you're able to manage your adjacency lists using relationships.
This package also supports Staudenmeir's Laravel Adjacency List package.
First, install the package:
composer require staudenmeir/laravel-adjacency-list:"^1.0"
HasRecursiveRelationships
trait in your model, and override the default path separator.// App/Models/Department.php class Department extends Model{ use \Staudenmeir\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships; public function getPathSeparator() { return '.children.'; }}
If you're already using the HasRecursiveRelationships trait for other parts of your application, it's probably not a good idea to change your model's path separator, since it can break other parts of your application. Instead, you can add as many path separators as you want:
class Department extends Model{ use \Staudenmeir\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships; public function getCustomPaths() { return [ [ 'name' => 'tree_path', 'column' => 'id', 'separator' => '.children.', ], ]; }}
relationship
method to define the relationship:AdjacencyList::make('subdepartments') ->relationship('descendants') // or 'descendantsAndSelf', 'children' ... ->customPath('tree_path') // if you're using custom paths
That's it! Now you're able to manage your adjacency lists using relationships.
AdjacencyList::make('subdepartments') ->relationship('descendants', fn (Builder $query): Builder => $query->where('enabled', 1))
If your application needs to order the items in the list, you can use the orderColumn
method:
AdjacencyList::make('subdepartments') ->orderColumn('sort') // or any other column
Please see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
Please review our security policy on how to report security vulnerabilities.
The MIT License (MIT). Please see License File for more information.
CTO, TALL Stack Developer at a Brazilian startup. Creating top-tier technology for public sector applications, making information and services universally accessible.