tourze/easy-admin-tree-select-field-bundle
Adds a tree-select field to EasyAdmin forms, letting editors pick nodes from hierarchical data like categories, menus, or org units in a searchable, nested dropdown. Install the bundle, register it, and use the field type in your CRUD controllers to choose parent records cleanly.
tourze/easy-admin-tree-select-field-bundle is a Symfony bundle (EasyAdmin field extension), not a Laravel package — despite the Laravel framing here, day one is about confirming that boundary. It ships a tree-select form field for choosing a node from a hierarchical entity (adjacency-list parent_id style tables) inside EasyAdmin CRUD controllers.
Minimal sequence:
composer require tourze/easy-admin-tree-select-field-bundle. This is a bundle, so there is no config/app.php provider entry — instead confirm the bundle is picked up by Flex (check config/bundles.php for the Tourze\EasyAdminTreeSelectFieldBundle\... entry; add it manually if Flex skipped it).composer.lock — field bundles are tightly coupled to EasyAdmin 4.x field APIs, and a 1.0.0 tag published with only an auto-generated changelog gives you no compatibility matrix. composer why-not is your first debugging tool.Field/ directory (the field class and its configureOptions) and any assets/ or Resources/ folder for the JS/CSS that renders the tree widget. That tells you which options are actually forwarded to the underlying form type.Category entity with parent self-referencing relation, wired into CategoryCrudController::configureFields() as the tree-select field for the parent relationship. Then test index (list) and edit (form) pages before going near new — creation is where empty-tree and root-node bugs show up.If you are on Laravel and arrived here by name collision: there is no service provider, no config/*.php publish tag, and no Eloquent bridge. Stop and look for a Laravel-native alternative unless you are running a Symfony app alongside.
Field configuration in the CRUD controller. The core pattern is adding the field to configureFields() and letting the bundle's field class handle option normalization. Keep entity, form, and index contexts distinct — tree rendering on index is usually a different (heavier) code path than on edit/new.
Self-referencing entity as the source of truth. The field expects a parent/child relation. Standard entity shape:
#[ORM\ManyToOne(targetEntity: Category::class, inversedBy: 'children')]
#[ORM\JoinColumn(onDelete: 'SET NULL')]
private ?Category $parent = null;
onDelete: 'SET NULL' matters — cascading deletes on a tree silently removes whole subtrees.
Repository-driven tree loading. Do not let the field pull children lazily per node. Add a repository method that returns the flat, ordered node set in one query and hand it in via the field's query-builder/choice options:
public function findTreeOrdered(): array
{
return $this->createQueryBuilder('c')
->orderBy('c.root, c.lft', 'ASC') // or c.name if adjacency-only
->getQuery()
->getResult();
}
Shared field configuration. If several CRUD controllers use the same tree, extract a small factory or trait rather than repeating options — this is the extension point that saves the most time when you upgrade EasyAdmin.
Integration with form themes and assets. For non-Flex installs, run bin/console assets:install --symlink after adding the bundle; the tree widget's JS will 404 otherwise and the field renders as a plain <select>, which is an easy-to-misread "the package is broken" symptom.
Migration/workflow pattern. When adopting on an existing flat table: add the parent column as nullable, backfill roots, populate relations in a one-off command or Doctrine migration, then flip the field on. Trees are painful to retrofit mid-flight, so stage it.
1.0.0 tag as "first stable API" only in the semver sense; there is no documented list of what changed, what is deprecated, or what is still experimental. Pin the exact version ("1.0.0" or ~1.0.0) and read the field class source before relying on any option name.config/ publish tag and find neither. Document the Symfony/EasyAdmin requirement in your own README so the next person does not burn an hour.configureOptions contracts. Run the EasyAdmin upgrade in its own commit with the tree field exercised on both index and edit.index is sluggish, restrict the tree field to form pages and show a breadcrumb/path string in the list instead.prePersist/preUpdate lifecycle callback or a Symfony validator constraint) — a cycle will hang the widget on next render, and the failure looks like a JS bug, not a data bug.dump()-ing the controller.templates/bundles/... path over forking the bundle; forking means you inherit maintenance for a package whose release notes you cannot audit.How can I help you explore Laravel packages today?