Working with hierarchical data can get complex quickly. Fortunately, there are tools to help. This bundle wraps 3 amazing tools together.
- a {% tree %} twig tag for recursively displaying a tree without writing a twig macro Wrapper for jstree using ApiPlatform. Also includes a {% tree %} twig tag.
- A stimulus controller that calls the jstree javascript library
- Some helpers to integrate with ApiPlatform for editing and creating tree nodes.
In addition to the above, the has a dependency on stof/doctrine-extensions-bundle to make doctrine entities hierarchical.
composer req survos/tree-bundle
The {% tree %}
tag works almost like {% for %}
, but inside a {% tree %}
you can call {% subtree var %}
See more details at tacman/tree-tag.
{% tree item in menu %}
{% if treeloop.first %}<ul>{% endif %}
<li>
<a href="{{ item.url }}">{{ item.name }}</a>
{% subtree item.children %}
</li>
{% if treeloop.last %}</ul>{% endif %}
{% endtree %}
symfony new tree-demo --webapp --version=next --php=8.2 && cd tree-demo
composer config minimum-stability dev
composer config extra.symfony.allow-contrib true
composer req symfony/asset-mapper:^6.4 symfony/stimulus-bundle:2.x-dev survos/tree-bundle
bin/console make:controller Tree -i
cat > templates/tree.html.twig <<END
{% extends 'base.html.twig' %}
{% block body %}
{% set food = [
{name: 'fruit', children: [
{name: 'apple', children: [
{name: 'Granny Smith'},
{name: 'Gala'},
{name: 'Fuji'},
]},
{name: 'banana'}
]},
{name: 'veggies', children: [
{name: 'peas'},
{name: 'carrots'},
{name: 'beets'}
]},
] %}
<h2>Food Tree</h2>
{% set _sc = '@survos/tree-bundle/tree' %}
<div {{ stimulus_controller(_sc) }} {{ stimulus_target(_sc, 'html') }}>
{% tree item in food %}
{% if treeloop.first %}<ul>{% endif %}
<li>
{{ item.name }}
{% subtree item.children|default([]) %}
</li>
{% if treeloop.last %}</ul>{% endif %}
{% endtree %}
</div>
{% endblock %}
END
symfony server:start -d
symfony open:local --path=/tree
"controllers": {
"tree": {
"main": "src/controllers/tree_controller.js",
"webpackMode": "eager",
"fetch": "lazy",
"enabled": true,
"autoimport": {
"jstree/dist/themes/default/style.min.css": true
}
},