Install the Bundle
Add to composer.json:
composer require dantleech/tree-ui-core-bundle
Enable in config/bundles.php:
Dantleech\TreeUiCoreBundle\DantleechTreeUiCoreBundle::class => ['all' => true],
Define a Tree Model
Implement Dantleech\TreeUiCoreBundle\Model\TreeNodeInterface for your entity (e.g., PHPCR-ODM, Doctrine ORM, or Filesystem).
Example for Filesystem (zero-config):
use Dantleech\TreeUiCoreBundle\Model\FilesystemTreeNode;
class MyFileNode extends FilesystemTreeNode
{
// Extend or override as needed
}
Register Metadata Use annotations or YAML to define tree structure. Example via annotation:
use Dantleech\TreeUiCoreBundle\Metadata\TreeMetadata;
/**
* @TreeMetadata(
* parentField="parent",
* childrenField="children",
* rootPath="/root"
* )
*/
class MyFileNode { ... }
Or via YAML (config/tree_ui/models/my_model.yaml):
tree_metadata:
parent_field: parent
children_field: children
root_path: "/root"
First Use Case: Tree Browser
Inject the TreeBrowser service in a controller:
use Dantleech\TreeUiCoreBundle\Service\TreeBrowser;
class TreeController extends AbstractController
{
public function browse(TreeBrowser $browser)
{
$tree = $browser->load('my_model');
return $this->render('tree/browser.html.twig', ['tree' => $tree]);
}
}
Render with a view bundle (e.g., TreeUiFancyTreeViewBundle).
Model Integration
TreeUiPhpcrOdmModelBundle to auto-map nodes.
use Dantleech\TreeUiPhpcrOdmBundle\Model\PhpcrTreeNode;
class DocumentNode extends PhpcrTreeNode { ... }
TreeNodeInterface manually or use a base class.FilesystemTreeNode for testing or static assets.View Integration
TreeUiFancyTreeViewBundle for drag-and-drop.
composer require dantleech/tree-ui-fancy-tree-view-bundle
StaticTreeView for debugging (no dependencies).CRUD Routes
Configure routes via YAML (config/tree_ui/routes.yaml):
tree_ui:
resource: "@TreeUiCoreBundle/Resources/config/routing.yml"
prefix: /admin/tree
defaults:
_controller: TreeUiCoreBundle:Default:tree
Override templates in templates/tree_ui/ to customize rendering.
Multi-Select Form
Use the TreeMultiSelectType in Symfony forms:
$builder->add('nodes', TreeMultiSelectType::class, [
'model' => 'my_model',
'choice_label' => 'name',
]);
TreeBrowser, TreeManager, and TreeMetadataFactory.TreeNodePrePersistEvent).TreeNodeInterface::getCacheKey() for performance.Metadata Configuration
root_path or children_field causes silent failures.$metadata = $metadataFactory->getMetadata('my_model');
if (!$metadata->isValid()) {
throw new \RuntimeException('Invalid tree metadata');
}
StaticTreeView for quick metadata testing.Drag-and-Drop Quirks
FancyTreeView requires jQuery and FancyTree JS. Missing dependencies break UI.TreeUiFancyTreeViewBundle assets are enqueued:
{{ encore_entry_link_tags('fancy-tree') }}
State Management
TreeStateStorageInterface or use session storage:
$browser->setStateStorage(new SessionTreeStateStorage());
Performance with Large Trees
TreeBrowser::loadWithChildren() with depth limits:
$tree = $browser->loadWithChildren('my_model', 0, 3); // Load root + 3 levels
Model Coupling
TreeNodeInterface methods are overlooked.AbstractTreeNode (if available) to reduce boilerplate.tree_ui.debug: true in config to log metadata and queries.$metadata = $metadataFactory->getMetadata('my_model');
dump($metadata->getParentField());
tree_ui/default/tree.html.twig to debug node data:
{% for node in tree %}
{{ dump(node) }}
{% endfor %}
Custom Metadata Sources
Implement TreeMetadataSourceInterface to load metadata from databases or APIs.
New Tree Views
Create a custom view by implementing TreeViewInterface:
class MyTreeView implements TreeViewInterface
{
public function render(TreeNodeInterface $node): string
{
return '<div>' . htmlspecialchars($node->getName()) . '</div>';
}
}
Event Subscribers
Listen to tree events (e.g., TreeNodePostRemoveEvent) to add logic:
class MyTreeSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
TreeEvents::NODE_POST_REMOVE => 'onNodeRemove',
];
}
public function onNodeRemove(NodePostRemoveEvent $event)
{
// Custom logic (e.g., log deletion)
}
}
Custom CRUD Actions
Extend the router configuration to add actions like reorder or export:
tree_ui_crud:
path: /admin/tree/{model}/reorder
defaults:
_controller: TreeUiCoreBundle:Default:reorder
model: my_model
```markdown
### Config Quirks
- **Bundle Order**: Ensure `TreeUiCoreBundle` loads **after** your model bundles (e.g., `TreeUiPhpcrOdmModelBundle`).
- **Route Conflicts**: Prefix routes explicitly to avoid clashes with Symfony’s default routes.
- **Annotation Processing**: Clear the cache after adding new `@TreeMetadata` annotations:
```bash
php bin/console cache:clear
How can I help you explore Laravel packages today?