Skip to content

Commit 86f59a9

Browse files
committed
Menu(v15): added typescript manifest examples + lit element example + explanation
1 parent 752dbb8 commit 86f59a9

File tree

1 file changed

+143
-7
lines changed
  • 15/umbraco-cms/customizing/extending-overview/extension-types

1 file changed

+143
-7
lines changed

15/umbraco-cms/customizing/extending-overview/extension-types/menu.md

Lines changed: 143 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,173 @@
44
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.
55
{% endhint %}
66

7-
## Menu
8-
97
<figure><img src="../../../.gitbook/assets/menu.png" alt="" width="250"><figcaption><p>Menu</p></figcaption></figure>
108

11-
```typescript
9+
**JSON Manifest:**
10+
```json
1211
{
1312
"type": "menu",
1413
"alias": "My.Menu",
1514
"name": "My Menu"
1615
}
1716
```
1817

19-
### Menu Item <a href="#menu-item" id="menu-item"></a>
18+
**Typescript Manifest:**
19+
```typescript
20+
import { ManifestMenu } from "@umbraco-cms/backoffice/extension-registry";
21+
22+
const menuManifest: Array<ManifestMenu> = [
23+
{
24+
type: 'menu',
25+
alias: 'My.Menu',
26+
name: 'My Menu'
27+
}
28+
];
29+
```
30+
31+
32+
## Menu Item <a href="#menu-item" id="menu-item"></a>
2033

2134
<figure><img src="../../../.gitbook/assets/menu-item.png" alt="" width="250"><figcaption><p>Menu Item</p></figcaption></figure>
2235

23-
```typescript
36+
### What is a Menu Item?
37+
38+
Menu items are the items that appear in the menu.
39+
40+
For adding custom menu items we can define a single MenuItem manifest and link an element to it. In this element we can fetch the data and render as many menu items as we want based on that data.
41+
42+
### JSON Manifest
43+
44+
```json
2445
{
2546
"type": "menuItem",
2647
"alias": "My.MenuItem",
2748
"name": "My Menu Item",
49+
"element": "./menu-items.ts",
2850
"meta": {
2951
"label": "My Menu Item",
3052
"menus": ["My.Menu"]
3153
}
3254
}
3355
```
3456

35-
### **Tree Menu Item**
57+
### Typescript Manifest
58+
```typescript
59+
const menuItemManifest: Array<ManifestMenuItem> = [
60+
{
61+
type: 'menuItem',
62+
alias: 'My.MenuItem',
63+
name: 'My Menu Item',
64+
meta: {
65+
label: 'My Menu Item',
66+
menus: ["My.Menu"]
67+
},
68+
element: () => import('./menu-items.ts')
69+
}
70+
];
71+
```
72+
73+
### The Lit Element
74+
75+
#### Rendering menu items with Umbraco's UI menu item component
76+
77+
To render your menu items in Umbraco, you can make use of the powerful [Umbraco UI Menu Item component](https://uui.umbraco.com/?path=/docs/uui-menu-item--docs). This component allows you to easily create nested menu structures with just a few lines of code.
78+
79+
To display the caret icon indicating nested items, you can set the `has-children` attribute dynamically like this: `?has-children=${bool}`.
80+
81+
**Example:**
82+
83+
```tsx
84+
<uui-menu-item label="Menu Item 1" has-children>
85+
<uui-menu-item label="Nested Menu Item 1"></uui-menu-item>
86+
<uui-menu-item label="Nested Menu Item 2"></uui-menu-item>
87+
</uui-menu-item>
88+
```
89+
90+
#### Custom menu item element example
91+
92+
Using this Lit element we can fetch the data and render the menu items. By putting the result of the fetch in a `@state()`, we can trigger a re-render of the component when the data is fetched.
93+
94+
**menu-items.ts:**
95+
```typescript
96+
import { UmbMenuItemElement } from '@umbraco-cms/backoffice/extension-registry';
97+
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
98+
import { html, TemplateResult } from 'lit';
99+
import { customElement, state } from 'lit/decorators.js';
100+
import { MyMenuItemResponseModel, MyMenuResource } from '../../../api';
101+
102+
const elementName = 'my-menu-item';
103+
104+
@customElement(elementName)
105+
class MyMenuItems extends UmbLitElement implements UmbMenuItemElement {
106+
@state()
107+
private _items: MyMenuItemResponseModel[] = []; // Store fetched items
108+
@state()
109+
private _loading: boolean = true; // Track loading state
110+
@state()
111+
private _error: string | null = null; // Track any errors
112+
113+
constructor() {
114+
super();
115+
this.fetchInitialItems(); // Start fetching on component load
116+
}
117+
118+
// Fetch initial items
119+
async fetchInitialItems() {
120+
try {
121+
this._loading = true;
122+
this._items = ((await MyMenuResource.getMenuApiV1()).items); // Fetch root-level items
123+
} catch (e) {
124+
this._error = 'Error fetching items';
125+
} finally {
126+
this._loading = false;
127+
}
128+
}
129+
130+
// Render items
131+
renderItems(items: MyMenuItemResponseModel[]): TemplateResult {
132+
return html`
133+
${items.map(element => html`
134+
<uui-menu-item label="${element.name}" ?has-children=${element.hasChildren}>
135+
${element.type === 1
136+
? html`<uui-icon slot="icon" name="icon-folder"></uui-icon>`
137+
: html`<uui-icon slot="icon" name="icon-autofill"></uui-icon>`}
138+
<!-- recursively render children -->
139+
${element.hasChildren ? this.renderItems(element.children) : ''}
140+
</uui-menu-item>
141+
`)}
142+
`;
143+
}
144+
145+
// Main render function
146+
render() {
147+
if (this._loading) {
148+
return html`<uui-loader></uui-loader>`;
149+
}
150+
151+
if (this._error) {
152+
return html`<uui-menu-item active disabled label="Could not load form tree!">
153+
</uui-menu-item>`;
154+
}
155+
156+
// Render items if loading is done and no error occurred
157+
return html`${this.renderItems(this._items)}`;
158+
}
159+
}
160+
161+
export { MyMenuItems as element };
162+
163+
declare global {
164+
interface HTMLElementTagNameMap {
165+
[elementName]: MyMenuItems;
166+
}
167+
}
168+
169+
```
170+
171+
## **Tree Menu Item**
36172

37-
#### **Manifest**
173+
### **Manifest**
38174

39175
```typescript
40176
// it will be something like this

0 commit comments

Comments
 (0)