Tree Picker

TreePicker lets the user pick one node of a tree, for example a folder to save or move a file into. It is a button that opens a panel with a search box and a Tree View. Choosing a node emits select with its key and closes the panel.

Usage

Selected key: nothing yet
<TreePicker items="$folders" selected="$target" label="Save into" placeholder="Choose a folder..." (select)="onPick" />
<div class="text-muted small mt-2">Selected key: {$target === null ? 'nothing yet' : $target}</div>
<?php

use Viewi\Components\BaseComponent;
use Viewi\UI\Components\Navigation\TreeNode;

class SaveFilePage extends BaseComponent
{
    public array $folders = [];
    public $target = null;

    public function mounted()
    {
        // key, label, depth, parentKey, icon, badge, title (the full path)
        $this->folders = [
            new TreeNode('docs', 'Documents', 1, null, 'bi-folder', '', 'Documents'),
            new TreeNode('docs-reports', 'Reports', 2, 'docs', 'bi-folder', '', 'Documents / Reports'),
            new TreeNode('docs-reports-2025', '2025', 3, 'docs-reports', 'bi-folder', '', 'Documents / Reports / 2025'),
            new TreeNode('docs-letters', 'Letters', 2, 'docs', 'bi-folder', '', 'Documents / Letters'),
            new TreeNode('photos', 'Photos', 1, null, 'bi-folder', '', 'Photos'),
            new TreeNode('photos-travel', 'Travel', 2, 'photos', 'bi-folder', '', 'Photos / Travel'),
            new TreeNode('photos-family', 'Family', 2, 'photos', 'bi-folder', '', 'Photos / Family'),
            new TreeNode('music', 'Music', 1, null, 'bi-folder', '', 'Music'),
        ];
    }

    public function onPick($key)
    {
        $this->target = $key;
    }
}

items are TreeNode objects in tree order, the same as for Tree View. Give each node a title with its full path, like Documents / Reports. The button shows it for the selected node, and the search matches against it.

The button text is text when it is set, else the path (title, or label when title is empty) of the selected node, else placeholder. TreePicker does not change selected by itself: handle select and set it.

Button with fixed text

Set text to use the picker as an action, like "Move to...". Rows in disabledKeys are shown but can not be chosen. Use it for the folder the file is already in.

The file is in Photos / Travel.
<TreePicker items="$folders" text="Move to..." icon="bi-folder-symlink" label="Move into"
    disabledKeys="$here" (select)="moveTo" />
public array $here = ['photos-travel'];

public function moveTo($key)
{
    $this->message = 'Moved to ' . $key;
}

Search

When the panel opens, the search box gets focus. While the user types, the tree shows only the matching nodes, as a flat list of their paths. If nothing matches, the panel shows "Nothing matches that.". The search ignores case.

  • A plain word matches nodes whose name contains it: rep finds Documents / Reports.
  • A term with / is a path. Each part must match a node on the way down, and the last part must match the node itself. Levels in between can be skipped: doc/2025 finds Documents / Reports / 2025.
  • A leading / means the first part must match a top-level node: /photos finds Photos but not a Photos folder deeper in the tree.
  • Spaces around the slashes do not matter.

The same matching is available in your own code as TreeSearch::matches($path, $name, $term) (Viewi\UI\Components\Navigation\TreeSearch). It returns true when the node with the full path $path (names joined with /) and the name $name matches $term. An empty term matches everything.

Closing

Choosing a node closes the panel, moves focus back to the button and emits select. Escape closes the panel and moves focus back to the button. A click outside the panel or on the button again closes it. Closing without choosing emits nothing.

Properties

TreePicker

items - list of TreeNode objects in tree order. See Tree View for how to build it. Default: [].

selected - (optional) key of the selected node. It is highlighted in the tree and its path is shown on the button. Default: null.

disabledKeys - (optional) keys of nodes that are shown but can not be chosen. Default: [].

label - (optional) accessible name of the button and the panel, also used as the button's tooltip. The search box is labelled "Find: " followed by it. Default: Choose.

text - (optional) fixed text of the button. Default: ` (empty), shows the selected path orplaceholder`.

placeholder - (optional) button text when nothing is selected and text is empty. Default: Choose....

icon - (optional) icon shown on the button before the text. Default: `` (empty), no icon.

buttonClass - (optional) class list of the button. Default: btn btn-outline-secondary btn-sm.

searchPlaceholder - (optional) placeholder of the search box. Default: Find....

align - (optional) horizontal alignment of the panel to the button. With start the left edges line up and the panel opens to the right. With end the right edges line up and the panel opens to the left. The panel is moved back inside the window if it does not fit. Default: start.

collapseOver - (optional) passed to the tree: up to this many nodes it starts fully expanded, with more it starts collapsed except the path to selected. 0 means always expanded. Default: 20.

Events

TreePicker

(select) - happens when the user chooses a node that is not disabled. The event value is the node's key.