# Building a tree with ReactiveHTML

**URL:** <https://discourse.holoviz.org/t/building-a-tree-with-reactivehtml/6438>\
**Category:** Panel\
**Tags:** tree\
**Created:** [November 20, 2023, 6:07pm UTC](https://discourse.holoviz.org/t/building-a-tree-with-reactivehtml/6438 "2023-11-20T18:07:00Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![jerry.vinokurov](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/jerry.vinokurov/32/5629_2.png) [@jerry.vinokurov](https://discourse.holoviz.org/u/jerry.vinokurov)\
**Post date:** [November 20, 2023, 6:07pm UTC](https://discourse.holoviz.org/t/building-a-tree-with-reactivehtml/6438/1 "2023-11-20T18:07:00Z")

</div>

Hello fellow Panel users,

I am building a data visualization app for work and I would like to represent certain parts of the app as a hierarchical tree. I’m familiar with JSTree and `panel-jstree` but I found the latter insufficiently flexible for what I wanted to do, and the documentation is quite sparse. Long story short, I decided to give `ReactiveHTML` a spin and implement the thing myself. Here’s what I came up with:

```python
import panel as pn
import param
from panel.reactive import ReactiveHTML

pn.extension()

class TreeNode(ReactiveHTML):

    node_id = param.String()
    children = param.List()
    label = param.String()
    toggled = param.Boolean()
    open = param.Boolean()

    def _toggle(self, event):
        self.toggled = not self.toggled
        self.toggle_children(self.toggled)

    def _label_click(self, event):
        pass

    def _expand_children(self, event=None):
        for child in self.children:
            child.open = True
            child._expand_children()
            
    _template = """
    <li id="node-{{ node_id }}">
        <details id="details-{{ node_id }}" open="${open}">
            <summary id="summary-{{ node_id }}" onclick="${_expand_children}">
                <input type="checkbox" id="checkbox" checked="${toggled}" onclick="${_toggle}"/>
                {{label}}
            </summary>
            <ul class="tree-children" id="tree-children">
                {% for child in children %}
                    <div id="child-container-{{ loop.index0 }}">
                        ${child}
                    </div>
                {% endfor %}
            </ul>
        </details>
    </li>
    """

    _dom_events = {'checkbox': ['change']}

    def _checkbox_change(self, event):
        pass

    def find_node(self, target_id):
        for child in self.children:
            if child.node_id == target_id:
                return child
            elif (result := child.find_node(target_id)) is not None:
                return result
        return None

    def insert_node(self, node, parent_id):

        parent = self.find_node(parent_id)
        print(parent_id, parent)
        if parent is not None:
            parent.children.append(node)

    def toggle_children(self, value):
        for child in self.children:
            child.toggled = value
            child.toggle_children(value)

class TreeRoot(TreeNode):

    _template = """
    <ul class="tree-root" id="tree-root">
        {% for child in children %}
            <div id="child-{{ loop.index0 }}">${child}</div>
        {% endfor %}
    </ul>
    """

    

```

![Screenshot 2023-11-20 at 1.02.17 PM](https://discourse.holoviz.org/uploads/default/original/2X/0/02ab85752c3de42264fc57a38976487e527b97f3.png)

I had to break up the tree into a special root node and general nodes, because the nodes themselves need to be mapped to `<li>` elements but the overall outer wrapping starts with a `<ul>`, so that breaks the recursivity. I’m sure there are other ways to do this using just divs and the appropriate JavaScript, but I’m not a JS expert so I haven’t bothered to figure out how to do that. Anyway, I hope this is useful to other people trying to build hierarchical representations in Panel. Happy to answer more questions about this.
