This page is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
Creating a custom menu
In this section, you can learn how to register and create a custom Menu for the Umbraco backoffice.
Manifest
The manifest file can be created using either JSON or TypeScript. Both methods are shown below.
We can create the manifest using JSON in the umbraco-package.json.
In this section, you can learn how to add custom Menu Items to your Umbraco backoffice Menu.
Manifest
To add custom menu items, you can define a single MenuItem manifest and link an element to it. In this element, you can fetch the data and render as many menu items as you want based on that data.
The code snippets below show how to declare a new menu item using JSON or TypeScript.
We can create the manifest using JSON in the umbraco-package.json.
{"type":"menuItem","alias":"My.MenuItem","name":"My Menu Item","element":"./menu-items.ts","meta": {"label":"My Menu Item","menus": ["My.Menu"] }}
The manifest can also be written in TypeScript.
For this TypeScript example we used a Backoffice Entry Point extension to register the manifests.
manifest.ts
constmenuItemManifest:Array<ManifestMenuItem> = [ { type:'menuItem', alias:'My.MenuItem', name:'My Menu Item', meta: { label:'My Menu Item', menus: ["My.Menu"] },element: () =>import('./menu-items.ts') }];
The UI Element
Rendering menu items with Umbraco's UI menu item component
To render your menu items in Umbraco, you can use the Umbraco UI Menu Item component. This component allows you to create nested menu structures with a few lines of code.
By default, you can set the has-children attribute to display the caret icon indicating nested items. It will look like this: ?has-children=${bool}.
Example:
<uui-menu-itemlabel="Menu Item 1"has-children> <uui-menu-itemlabel="Nested Menu Item 1"></uui-menu-item> <uui-menu-itemlabel="Nested Menu Item 2"></uui-menu-item></uui-menu-item>
Custom menu item element example
You can fetch the data and render the menu items using the Lit element above. By putting the result of the fetch in a @state(), we can trigger a re-render of the component when the data is fetched.
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 { MyMenuItemResponseModel, MyMenuResource } from'../../../api';constelementName='my-menu-item';@customElement(elementName)classMyMenuItemsextendsUmbLitElementimplementsUmbMenuItemElement { @state()private _items:MyMenuItemResponseModel[] = []; // Store fetched items @state()private _loading:boolean=true; // Track loading state @state()private _error:string|null=null; // Track any errorsconstructor() {super();this.fetchInitialItems(); // Start fetching on component load }// Fetch initial itemsasyncfetchInitialItems() {try {this._loading =true;this._items = ((awaitMyMenuResource.getMenuApiV1()).items); // Fetch root-level items } catch (e) {this._error ='Error fetching items'; } finally {this._loading =false; } }// Render itemsrenderItems(items:MyMenuItemResponseModel[]):TemplateResult {returnhtml`${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>`} <!-- recursively render children -->${element.hasChildren ?this.renderItems(element.children) :''} </uui-menu-item> `)} `; }// Main render functionrender() {if (this._loading) {returnhtml`<uui-loader></uui-loader>`; }if (this._error) {returnhtml`<uui-menu-item active disabled label="Could not load form tree!"> </uui-menu-item>`; }// Render items if loading is done and no error occurredreturnhtml`${this.renderItems(this._items)}`; }}export { MyMenuItems as element };declare global {interfaceHTMLElementTagNameMap { [elementName]:MyMenuItems; }}
Tree Menu Item
Manifest
// it will be something like this{"type": "menuItem","kind": "tree","alias": "My.TreeMenuItem","name": "My Tree Menu Item","meta": {"label":"My Tree Menu Item","menus": ["My.Menu"] }}
Default Element
// get interfaceinterfaceUmbTreeMenuItemElement {}
Adding menu items to an existing menu
The backoffice comes with a couple of menus.
Content, Media, Settings, Templating, Dictionary, etc.
To add a menu item to an existing menu, you can use the meta.menus property.
{"type": "menuItem","alias": "My.MenuItem","name": "My Menu Item","meta": {"label":"My Menu Item","menus": ["Umb.Menu.Content"] }}