Skip to content

Commit 5b275a6

Browse files
authored
Merge pull request #6456 from Yinzy00/feature/add-menu-docs
Menu: Added extra examples + explanation
2 parents 627e916 + 2928f27 commit 5b275a6

File tree

2 files changed

+386
-18
lines changed
  • 14/umbraco-cms/customizing/extending-overview/extension-types
  • 15/umbraco-cms/customizing/extending-overview/extension-types

2 files changed

+386
-18
lines changed

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

Lines changed: 193 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,221 @@
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+
## Creating a custom menu
10+
11+
In this section, you can learn how to register and create a custom Menu for the Umbraco backoffice.
12+
13+
### Manifest
14+
15+
The manifest file can be created using either JSON or TypeScript. Both methods are shown below.
16+
17+
{% tabs %}
18+
19+
{% tab title="JSON" %}
20+
21+
We can create the manifest using JSON in the `umbraco-package.json`.
22+
23+
```json
1224
{
1325
"type": "menu",
1426
"alias": "My.Menu",
1527
"name": "My Menu"
1628
}
1729
```
30+
{% endtab %}
1831

19-
### Menu Item <a href="#menu-item" id="menu-item"></a>
32+
{% tab title="TypeScript" %}
2033

21-
<figure><img src="../../../.gitbook/assets/menu-item.png" alt="" width="250"><figcaption><p>Menu Item</p></figcaption></figure>
34+
The manifest can also be written in TypeScript.
35+
36+
For this TypeScript example we used a [Backoffice Entry Point](../../extending-overview/extension-types/backoffice-entry-point) extension to register the manifests
2237

2338
```typescript
39+
import { ManifestMenu } from "@umbraco-cms/backoffice/extension-registry";
40+
41+
const menuManifest: Array<ManifestMenu> = [
42+
{
43+
type: 'menu',
44+
alias: 'My.Menu',
45+
name: 'My Menu'
46+
}
47+
];
48+
```
49+
50+
{% endtab %}
51+
52+
{% endtabs %}
53+
54+
# Menu Item
55+
56+
<figure><img src="../../../.gitbook/assets/menu-item.png" alt="" width="250"><figcaption><p>Menu Item</p></figcaption></figure>
57+
58+
Menu items are the items that appear in the menu.
59+
60+
## Creating a custom menu items
61+
62+
In this section, you can learn how to add custom Menu Items to your Umbraco backoffice Menu.
63+
64+
### Manifest
65+
66+
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.
67+
68+
The code snippets below show how to declare a new menu item using JSON or TypeScript.
69+
70+
{% tabs %}
71+
72+
{% tab title="JSON" %}
73+
74+
We can create the manifest using JSON in the `umbraco-package.json`.
75+
76+
```json
2477
{
2578
"type": "menuItem",
2679
"alias": "My.MenuItem",
2780
"name": "My Menu Item",
81+
"element": "./menu-items.ts",
2882
"meta": {
2983
"label": "My Menu Item",
3084
"menus": ["My.Menu"]
3185
}
3286
}
3387
```
3488

35-
### **Tree Menu Item**
89+
{% endtab %}
90+
91+
{% tab title="TypeScript" %}
92+
93+
The manifest can also be written in TypeScript.
94+
95+
For this TypeScript example we used a [Backoffice Entry Point](../../extending-overview/extension-types/backoffice-entry-point) extension to register the manifests
96+
97+
{% code title="manifest.ts" %}
98+
```typescript
99+
const menuItemManifest: Array<ManifestMenuItem> = [
100+
{
101+
type: 'menuItem',
102+
alias: 'My.MenuItem',
103+
name: 'My Menu Item',
104+
meta: {
105+
label: 'My Menu Item',
106+
menus: ["My.Menu"]
107+
},
108+
element: () => import('./menu-items.ts')
109+
}
110+
];
111+
```
112+
{% endcode %}
113+
114+
115+
{% endtab %}
116+
117+
{% endtabs %}
118+
119+
### The UI Element
120+
121+
#### Rendering menu items with Umbraco's UI menu item component
122+
123+
To render your menu items in Umbraco, you can use the [Umbraco UI Menu Item component](https://uui.umbraco.com/?path=/docs/uui-menu-item--docs). This component allows you to create nested menu structures with a few lines of code.
124+
125+
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}`.
126+
127+
**Example:**
128+
129+
```tsx
130+
<uui-menu-item label="Menu Item 1" has-children>
131+
<uui-menu-item label="Nested Menu Item 1"></uui-menu-item>
132+
<uui-menu-item label="Nested Menu Item 2"></uui-menu-item>
133+
</uui-menu-item>
134+
```
135+
136+
#### Custom menu item element example
137+
138+
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.
139+
140+
{% code title="menu-items.ts" %}
141+
```typescript
142+
import { UmbMenuItemElement } from '@umbraco-cms/backoffice/extension-registry';
143+
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
144+
import { html, TemplateResult } from 'lit';
145+
import { customElement, state } from 'lit/decorators.js';
146+
import { MyMenuItemResponseModel, MyMenuResource } from '../../../api';
147+
148+
const elementName = 'my-menu-item';
149+
150+
@customElement(elementName)
151+
class MyMenuItems extends UmbLitElement implements UmbMenuItemElement {
152+
@state()
153+
private _items: MyMenuItemResponseModel[] = []; // Store fetched items
154+
@state()
155+
private _loading: boolean = true; // Track loading state
156+
@state()
157+
private _error: string | null = null; // Track any errors
158+
159+
constructor() {
160+
super();
161+
this.fetchInitialItems(); // Start fetching on component load
162+
}
163+
164+
// Fetch initial items
165+
async fetchInitialItems() {
166+
try {
167+
this._loading = true;
168+
this._items = ((await MyMenuResource.getMenuApiV1()).items); // Fetch root-level items
169+
} catch (e) {
170+
this._error = 'Error fetching items';
171+
} finally {
172+
this._loading = false;
173+
}
174+
}
175+
176+
// Render items
177+
renderItems(items: MyMenuItemResponseModel[]): TemplateResult {
178+
return html`
179+
${items.map(element => html`
180+
<uui-menu-item label="${element.name}" ?has-children=${element.hasChildren}>
181+
${element.type === 1
182+
? html`<uui-icon slot="icon" name="icon-folder"></uui-icon>`
183+
: html`<uui-icon slot="icon" name="icon-autofill"></uui-icon>`}
184+
<!-- recursively render children -->
185+
${element.hasChildren ? this.renderItems(element.children) : ''}
186+
</uui-menu-item>
187+
`)}
188+
`;
189+
}
190+
191+
// Main render function
192+
render() {
193+
if (this._loading) {
194+
return html`<uui-loader></uui-loader>`;
195+
}
196+
197+
if (this._error) {
198+
return html`<uui-menu-item active disabled label="Could not load form tree!">
199+
</uui-menu-item>`;
200+
}
201+
202+
// Render items if loading is done and no error occurred
203+
return html`${this.renderItems(this._items)}`;
204+
}
205+
}
206+
207+
export { MyMenuItems as element };
208+
209+
declare global {
210+
interface HTMLElementTagNameMap {
211+
[elementName]: MyMenuItems;
212+
}
213+
}
214+
215+
```
216+
{% endcode %}
217+
218+
219+
## Tree Menu Item
36220

37-
#### **Manifest**
221+
### Manifest
38222

39223
```typescript
40224
// it will be something like this
@@ -50,14 +234,14 @@ This page is a work in progress and may undergo further revisions, updates, or a
50234
}
51235
```
52236

53-
#### **Default Element**
237+
#### Default Element
54238

55239
```typescript
56240
// get interface
57241
interface UmbTreeMenuItemElement {}
58242
```
59243

60-
### **Adding menu items to an existing menu**
244+
### Adding menu items to an existing menu
61245

62246
The backoffice comes with a couple of menus.
63247

0 commit comments

Comments
 (0)