codewithdennis/filament-select-tree
Dynamic select tree field for Laravel Filament that renders hierarchical dropdowns from relationships or custom queries. Supports BelongsTo and BelongsToMany, parent/child attributes, and customizable parent/child query scopes with optional strict root behavior.
BelongsTo, BelongsToMany), reducing boilerplate for querying hierarchical data. Supports custom queries for non-relational use cases.getTreeUsing), dynamic filtering, and pre/post-processing, making it adaptable to edge cases (e.g., hybrid data sources or non-database hierarchies).filament:assets command is standard for Filament packages. No complex migrations or database changes required.treeselectjs) are well-maintained.getTreeUsing with dynamic data) require careful implementation to avoid N+1 queries or memory leaks. Use storeResults() judiciously.strictNullParentRootNodes or withTrashed introduce subtle query behavior. Validate with test data covering orphaned nodes, soft deletes, and filtered states.Data Model Compatibility:
parent_id fields, or will custom mappings (e.g., parent_code) be needed?Performance Requirements:
User Experience:
BelongsToMany) or single-select (default for BelongsTo)? Can this vary by context?Maintenance:
getTreeUsing) be documented and tested for future-proofing?Alternatives:
select fields or a custom Vue component) meet requirements with less risk? Justify the trade-offs of this package’s complexity.SelectTree::make().4.x tag).treeselectjs (included via Filament’s asset pipeline). No additional build steps needed.Assessment Phase:
enableBranchNode() for category filters?").Pilot Implementation:
->relationship('categories', 'name', 'parent_id')).->withCount(), ->searchable()).use CodeWithDennis\FilamentSelectTree\SelectTree;
SelectTree::make('categories')
->relationship('categories', 'name', 'parent_id')
->searchable()
->placeholder('Select a category...');
Scaling to Tables/Filters:
Filter example from the README:
Filter::make('category')
->form([
SelectTree::make('categories')
->relationship('categories', 'name', 'parent_id')
->enableBranchNode(),
])
->query(fn(Builder $query, array $data) => $query->whereHas('categories', fn($q) => $q->whereIn('id', $data['categories'])));
indicateUsing() and query logic handle edge cases (e.g., empty selections).Advanced Customization:
getTreeUsing() with closures or static arrays:
SelectTree::make('custom_tree')
->getTreeUsing(fn() => $this->buildDynamicTree())
->treeKey('custom-tree');
prepend()/append() for static nodes (e.g., "All Categories" or "Uncategorized" options).parent_id or custom parent keys. Test with:
parent_id foreign keys.parent_code) via ->withKey('code').->withTrashed()).->modifyQueryUsing(fn($query) => $query->cachedFor(60))
__() for placeholders/labels. Ensure translation keys align with your app’s locale files.treeselectjs and Filament for breaking changes. Subscribe to:
TreeField trait or helper class) to reduce duplication.getTreeUsing logic) in comments or a wiki.getTreeUsing closures).parent_id queries return data. Check strictNullParentRootNodes() if children are orphaned.How can I help you explore Laravel packages today?