Trees

A guide to creating a custom tree in Umbraco

The tree is a hierarchical structure of nodes and is registered in the Backoffice extension registry. A tree can be rendered anywhere in the Backoffice with the help of the <umb-tree /> element.

To see how to register a tree as a menu in a section, please refer to the Section Sidebar article.

Creating trees

To create a Tree in the Backoffice, you need to take multiple steps:

Registering a tree

To register a tree, you need to create a manifest:

{
    "type": "tree",
    "alias": "My.Tree.Alias",
    "name": "My Tree",
    "meta": {
        "repositoryAlias": "My.Repository.Alias"
    }
}

Rendering a tree

To render a tree in the Backoffice, you can use the <umb-tree> element. You need to provide the alias of the tree you want to render. The alias is the same as the one you registered in the manifest.

<umb-tree alias="My.Tree.Alias"></umb-tree>

Render a Custom Tree Item

The <umb-tree /> element will render the tree items based on the registered tree item alias. The tree will be rendered using the element by default. If you want to render a custom tree item, you need to register a tree item manifest. This manifest can then show a custom element for the tree item.

The Tree Item Manifest

{
    "type": "treeItem",
    "alias": "Umb.TreeItem.Alias",
    "name": "My Tree Item",
    "element": "./my-tree-item.element.js",
    "conditions": {
        "entityType": "my-entity-type",
    },
};

The Tree Item Element

To create a custom tree item, you need to create a custom element. This element can optionally extend the UmbTreeItemElementBase class. However, it can also be used as a standalone element if you prefer to implement the tree item logic yourself.

This example creates a custom tree item that extends the base class. The base class provides the necessary context and functionality for the tree item.

import type { MyTreeItemDataModel } from './my-tree-item.model.js';
import { UmbTreeItemElementBase } from '@umbraco-cms/backoffice/tree';
import { html, nothing, customElement } from '@umbraco-cms/backoffice/external/lit';

@customElement('my-tree-item')
export class MyTreeItemElement extends UmbTreeItemElementBase<MyTreeItemDataModel> {
    override render() {
        if (!this.item) return nothing;
        return html`
            <div>
                <umb-icon .name=${this.item.icon}></umb-icon>
                <span>${this.item.name}</span>
            </div>
        `;
    }
}

export default MyTreeItemElement;

The Tree Item Model

To define the data model for your tree item, you can create a model that extends the UmbTreeItemModel. This model will be used to provide the data for your custom tree item.

my-tree-item.model.ts
import type { UmbTreeItemModel } from '@umbraco-cms/backoffice/tree';

export interface MyTreeItemDataModel extends UmbTreeItemModel {
    // Add any additional properties you need for your tree item
}

Adding data to the tree

To add data to the tree, you need to create a repository that will provide the data for the tree. The repository is defined in the manifest of the tree and linked through its repositoryAlias.

{
    "type": "repository",
    "alias": "My.Repository.Alias",
    "name": "My Repository",
    "api": "./my-repository.js"
}

Implementing the repository

The repository needs to be able to fetch data for the tree. You can implement the repository as a class that extends the UmbTreeRepositoryBase class. This class provides the necessary methods to fetch data for the tree.

my-repository.ts
import { MyTreeDataSource } from './my-tree-data-source.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbTreeRepositoryBase } from '@umbraco-cms/backoffice/tree';

export class MyRepository extends UmbTreeRepositoryBase {
    constructor(host: UmbControllerHost) {
        super(host, MyTreeDataSource);
    }
}

Implementing the data source

The data source is responsible for fetching the data for the tree. You can implement the data source as a class that implements the UmbTreeDataSource interface.

my-tree-data-source.ts
import type { MyTreeItemModel } from './my-tree-item.model.js';
import type {
	UmbTreeAncestorsOfRequestArgs,
	UmbTreeChildrenOfRequestArgs,
	UmbTreeDataSource,
	UmbTreeRootItemsRequestArgs,
} from '@umbraco-cms/backoffice/tree';

export class MyTreeDataSource implements UmbTreeDataSource<MyTreeItemModel> {
    async getRootItems(args: UmbTreeRootItemsRequestArgs) {
        // Fetch the root items for the tree
        return [
            {
                id: 'root1',
                name: 'Root Item 1',
                icon: 'icon-folder',
            },
            {
                id: 'root2',
                name: 'Root Item 2',
                icon: 'icon-folder',
            },
        ];
    }

    async getChildrenOf(args: UmbTreeChildrenOfRequestArgs) {
        // Fetch the children of the specified item
        if (args.id === 'root1') {
            return [
                {
                    id: 'child1',
                    name: 'Child Item 1',
                    icon: 'icon-document',
                },
                {
                    id: 'child2',
                    name: 'Child Item 2',
                    icon: 'icon-document',
                },
            ];
        }
        return [];
    }

    async getAncestorsOf(args: UmbTreeAncestorsOfRequestArgs) {
        // Fetch the ancestors of the specified item
        if (args.id === 'child1') {
            return [
                {
                    id: 'root1',
                    name: 'Root Item 1',
                    icon: 'icon-folder',
                },
            ];
        }
        return [];
    }
}

Further reading

For more information on trees, you can refer to the examples folder in the GitHub repository: Umbraco UI Examples - Trees

Last updated

Was this helpful?