Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungThe Indie Dev Visibility Playbook: From Zero Users to Your First 100(21.09.2026 um 00:08 Uhr)
Sichere ProgrammierungBase, Chat and Reasoning Models: How Are They Different?(21.09.2026 um 00:09 Uhr)
Sichere ProgrammierungHexfield Deck is for Kanban lovers and Markdown believers(21.09.2026 um 00:20 Uhr)
Sichere ProgrammierungPermissions and Authorisation: A Practical Playbook(21.09.2026 um 00:21 Uhr)
Linux Tipps & Hardeningfilet | Terminal File Manager(20.09.2026 um 21:03 Uhr)
Linux Tipps & HardeningLooking for feedback on my Linux Distro(20.09.2026 um 21:03 Uhr)
Sichere ProgrammierungThe Indie Dev Visibility Playbook: From Zero Users to Your First 100(21.09.2026 um 00:08 Uhr)
Sichere ProgrammierungBase, Chat and Reasoning Models: How Are They Different?(21.09.2026 um 00:09 Uhr)
Sichere ProgrammierungHexfield Deck is for Kanban lovers and Markdown believers(21.09.2026 um 00:20 Uhr)
Sichere ProgrammierungPermissions and Authorisation: A Practical Playbook(21.09.2026 um 00:21 Uhr)
Linux Tipps & Hardeningfilet | Terminal File Manager(20.09.2026 um 21:03 Uhr)
Linux Tipps & HardeningLooking for feedback on my Linux Distro(20.09.2026 um 21:03 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Building Custom Trees in Umbraco 14 using menus!

Reagiere als Erste:r — dein Feedback zählt!

Table of Contents

  1. Some Thoughts
  2. Building Custom Menu Item Components
    • Rendering Menu Items with Umbraco's UI Menu Item Component
    • Example: Fetching and Rendering a Dynamic Tree
  3. Manifests
    • Defining the Tree Space with ManifestSectionSidebarApp
    • Defining the Menu with ManifestMenu
    • Linking the Custom Elements with ManifestMenuItem
  4. Final Result

Some Thoughts

There are several methods to create custom trees. One approach is using a full Tree structure, which involves numerous components like ManifestTree, ManifestTreeItem, ManifestTreeStore, DataSource, Repository, and many more files.

File structure Umbraco document section

However, I find this approach overly complex and unnecessary for small, simple trees.

For a basic tree with, I prefer using a menu with custom-rendered menu items using a custom Lit element, as I will demonstrate in this example.

Building Custom Menu Item Components

Rendering Menu Items with Umbraco's UI Menu Item Component

To render your menu items in Umbraco, you can make use of the powerful Umbraco UI Menu Item component. This component allows you to easily create nested menu structures with just a few lines of code.

Example:

<uui-menu-item label="Menu Item 1" has-children>
    <uui-menu-item label="Nested Menu Item 1"></uui-menu-item>
    <uui-menu-item label="Nested Menu Item 2"></uui-menu-item>
</uui-menu-item>

Image of result example code

Example: Fetching and Rendering a Dynamic Tree

In this example, the entire tree is fetched when the component is rendered. Once the data is loaded, we put the items in a @state(). This will trigger a re-render of the tree because it is a reactive property.

With the retrieved data, I dynamically render nested menu items, each with relevant icons. The core functionality of the tree such as opening, closing, and indenting nodes comes from the menu item component itself.

To display the caret icon indicating nested items, you can set the has-children attribute dynamically like this: ?has-children=${bool}.

menu-items.ts:

import { UmbMenuItemElement } from '@umbraco-cms/backoffice/extension-registry';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { html, TemplateResult } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { FormXTreeItemResponseModel, FormXTreeResource } from '../../../api';


const elementName = 'formx-menu-item';

@customElement(elementName)
class FormXMenuItems extends UmbLitElement implements UmbMenuItemElement {
    @state()
    private _items: FormXTreeItemResponseModel[] = []; // Store fetched items
    @state()
    private _loading: boolean = true; // Track loading state
    @state()
    private _error: string | null = null; // Track any errors

    constructor() {
        super();
        this.fetchInitialItems(); // Start fetching on component load
    }

    // Fetch initial items
    async fetchInitialItems() {
        try {
            this._loading = true;
            this._items = ((await FormXTreeResource.getFormxApiV1Tree()).items); // Fetch root-level items
        } catch (e) {
            this._error = 'Error fetching items';
        } finally {
            this._loading = false;
        }
    }

    // Render items
    renderItems(items: FormXTreeItemResponseModel[]): TemplateResult {
        return html`
            ${items.map(element => html`
                <uui-menu-item label="${element.name}" ?has-children=${element.hasChildren}>
                ${element.type === 1 
                ? html`<uui-icon slot="icon" name="icon-folder"></uui-icon>` 
                : html`<uui-icon slot="icon" name="icon-autofill"></uui-icon>`}
                    ${element.hasChildren ? this.renderItems(element.children) : ''}
                </uui-menu-item>
            `)}
        `;
    }

    // Main render function
    render() {
        if (this._loading) {
            return html`<uui-loader></uui-loader>`;
        }

        if (this._error) {
            return html`<uui-menu-item active disabled label="Could not load form tree!">
        </uui-menu-item>`;
        }

        // Render items if loading is done and no error occurred
        return html`${this.renderItems(this._items)}`;
    }
}



export { FormXMenuItems as element };

declare global {
    interface HTMLElementTagNameMap {
        [elementName]: FormXMenuItems;
    }
}

The result will be a menu that looks like the following:

Result of what our custom element would look like.

Manifests

For this setup, you'll need three key manifests that work together to render a tree using a custom menu.

Let’s start by defining a reusable alias:

const FORMX_MENU_ALIAS = "Our.Umbraco.FormX.menu";

Defining the Tree Space with ManifestSectionSidebarApp

The first manifest defines the space where your tree will appear. This is achieved by creating a ManifestSectionSidebarApp. We can connect the menu to the sidebar using the menu alias.

const sidebarApps: Array<ManifestSectionSidebarApp> = [
    {
        type: 'sectionSidebarApp',
        kind: 'menuWithEntityActions',
        alias: 'Our.Umbraco.FormX.sidebar',
        name: 'FormX Sidebar App',
        meta: {
            label: "Forms",
            menu: FORMX_MENU_ALIAS
        },
        conditions: [
            {
                alias: "Umb.Condition.SectionAlias",
                match: "Our.Umbraco.FormX.section"
            }
        ]
    }
];

Defining the Menu with ManifestMenu

Next, you’ll define the actual menu where your items will be rendered. For this we can use a ManifestMenu.

const menuManifest: Array<ManifestMenu> = [
    {
        type: 'menu',
        alias: FORMX_MENU_ALIAS,
        name: 'FormX Menu'
    }
];

Linking the Custom Elements with ManifestMenuItem

Lastly, we need to link our custom elements that fetch and render your menu items. This is where the ManifestMenuItem comes in.

const menuItemManifest: Array<ManifestMenuItem> = [
    {
        type: 'menuItem',
        alias: 'formx-menu-items',
        name: 'FormX Menu Items',
        meta: {
            label: 'FormX',
            menus: [FORMX_MENU_ALIAS]
        },
        element: () => import('./menu-items.ts')
    }
];

Final Result

Once the SectionSidebarApp is linked to our custom section, the tree will be rendered with the specified label and custom elements.

Example of what our custom section with our newly created custom tree would look like.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Building Custom Trees in Umbraco 14 using menus!

Thematisch verwandte Begriffe: Building, Custom, Trees, Umbraco · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-93957 | A vulnerability has been found in olivier-ls PHP-FTS up to 1.1.3. This a…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick