@@ -18,9 +18,16 @@ Menu extensions can be created using either JSON or TypeScript. Both approaches
1818{% code title="umbraco-package.json" %}
1919``` json
2020{
21- "type" : " menu" ,
22- "alias" : " My.Menu" ,
23- "name" : " My Menu"
21+ "$schema" : " ../../umbraco-package-schema.json" ,
22+ "name" : " My Package" ,
23+ "version" : " 0.1.0" ,
24+ "extensions" : [
25+ {
26+ "type" : " menu" ,
27+ "alias" : " My.Menu" ,
28+ "name" : " My Menu"
29+ }
30+ ]
2431}
2532```
2633{% endcode %}
@@ -32,13 +39,11 @@ Extension authors define the menu manifest, then register it dynamically/during
3239``` typescript
3340import type { ManifestMenu } from ' @umbraco-cms/backoffice/menu' ;
3441
35- export const menuManifest: Array <ManifestMenu > = [
36- {
37- type: ' menu' ,
38- alias: ' My.Menu' ,
39- name: ' My Menu'
40- }
41- ];
42+ export const menuManifest: ManifestMenu = {
43+ type: ' menu' ,
44+ alias: ' My.Menu' ,
45+ name: ' My Menu'
46+ };
4247```
4348{% endcode %}
4449
@@ -79,14 +84,21 @@ To add custom menu items, you can define a single MenuItem manifest and link an
7984{% code title="umbraco-package.json" %}
8085``` json
8186{
82- "type" : " menuItem" ,
83- "alias" : " My.MenuItem" ,
84- "name" : " My Menu Item" ,
85- "element" : " ./menu-items.ts" ,
86- "meta" : {
87- "label" : " My Menu Item" ,
88- "menus" : [" My.Menu" ]
89- }
87+ "$schema" : " ../../umbraco-package-schema.json" ,
88+ "name" : " My Package" ,
89+ "version" : " 0.1.0" ,
90+ "extensions" : [
91+ {
92+ "type" : " menuItem" ,
93+ "alias" : " My.MenuItem" ,
94+ "name" : " My Menu Item" ,
95+ "element" : " ./menu-items.ts" ,
96+ "meta" : {
97+ "label" : " My Menu Item" ,
98+ "menus" : [" My.Menu" ]
99+ }
100+ }
101+ ]
90102}
91103```
92104{% hint style="info" %}
@@ -102,17 +114,17 @@ The `element` attribute will point toward a custom Lit component, an example of
102114
103115{% code title="my-menu/manifests.ts" %}
104116``` typescript
105- const menuItemManifest : Array < ManifestMenuItem > = [
106- {
107- type: ' menuItem ' ,
108- alias : ' My.MenuItem ' ,
109- name : ' My Menu Item ' ,
110- meta: {
111- label: ' My Menu Item ' ,
112- menus: [ " My. Menu" ]
113- },
114- }
115- ] ;
117+ import type { ManifestMenuItem } from ' @umbraco-cms/backoffice/menu ' ;
118+
119+ export const menuItemManifest : ManifestMenuItem = {
120+ type : ' menuItem ' ,
121+ alias : ' My.MenuItem ' ,
122+ name: ' My Menu Item ' ,
123+ meta: {
124+ label: ' My Menu Item ' ,
125+ menus: [ " My.Menu " ]
126+ },
127+ } ;
116128```
117129{% endcode %}
118130
@@ -134,123 +146,6 @@ export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => {
134146{% endtab %}
135147{% endtabs %}
136148
137- ### Custom menu items
138-
139- {% hint style="info" %}
140- ** Note:** Displaying menu item extensions does not require extension authors to create custom menu item subclasss. This step is optional.
141- {% endhint %}
142-
143- To render your menu items in Umbraco, extension authors can use the [ Umbraco UI Menu Item component] ( https://uui.umbraco.com/?path=/docs/uui-menu-item--docs ) . This component enables nested menu structures with a few lines of markup.
144-
145- ` <uui-menu-item> ` nodes accept the ` has-children ` boolean attribute, which will display a caret icon indicating nested items. Tying this boolean attribute to a variable requires using the ` ? ` Lit directive, which would look similar to this: ` ?has-children=${boolVariable} ` .
146-
147- ** Example:**
148-
149- ``` html
150- <uui-menu-item label =" Menu Item 1" has-children >
151- <uui-menu-item label =" Nested Menu Item 1" ></uui-menu-item >
152- <uui-menu-item label =" Nested Menu Item 2" ></uui-menu-item >
153- </uui-menu-item >
154- ```
155-
156- ### Custom menu item element example
157-
158- Custom elements can fetch the data and render menu items using markup, like above. Storing the results of the fetch in a ` @state() ` variable will trigger a re-render of the component when the value of the variable changes.
159-
160- {% code title="menu-items.ts" overflow="wrap" lineNumbers="true" %}
161- ``` typescript
162- import type { UmbMenuItemElement } from ' @umbraco-cms/backoffice/menu' ;
163- import { UmbLitElement } from ' @umbraco-cms/backoffice/lit-element' ;
164- import { html , TemplateResult , customElement , state } from ' @umbraco-cms/backoffice/external/lit' ;
165- import { MyMenuItemResponseModel , MyMenuResource } from ' ../../../api' ;
166-
167- const elementName = ' my-menu-item' ;
168-
169- @customElement (elementName )
170- class MyMenuItems extends UmbLitElement implements UmbMenuItemElement {
171- @state ()
172- private _items: MyMenuItemResponseModel [] = []; // Store fetched items
173-
174- @state ()
175- private _loading: boolean = true ; // Track loading state
176-
177- @state ()
178- private _error: string | null = null ; // Track any errors
179-
180- override firstUpdated() {
181- this .fetchInitialItems (); // Start fetching on component load
182- }
183-
184- // Fetch initial items
185- async fetchInitialItems() {
186- try {
187- this ._loading = true ;
188- this ._items = ((await MyMenuResource .getMenuApiV1 ()).items ); // Fetch root-level items
189- } catch (e ) {
190- this ._error = ' Error fetching items' ;
191- } finally {
192- this ._loading = false ;
193- }
194- }
195-
196- // Render items
197- renderItems(items : MyMenuItemResponseModel []): TemplateResult {
198- return html `
199- ${items .map (element => html `
200- <uui-menu-item label="${element .name }" ?has-children=${element .hasChildren }>
201- ${element .type === 1
202- ? html ` <uui-icon slot="icon" name="icon-folder"></uui-icon> `
203- : html ` <uui-icon slot="icon" name="icon-autofill"></uui-icon> ` }
204- <!-- recursively render children -->
205- ${element .hasChildren ? this .renderItems (element .children ) : ' ' }
206- </uui-menu-item>
207- ` )}
208- ` ;
209- }
210-
211- // Main render function
212- override render() {
213- if (this ._loading ) {
214- return html ` <uui-loader></uui-loader> ` ;
215- }
216-
217- if (this ._error ) {
218- return html ` <uui-menu-item active disabled label="Could not load form tree!">
219- </uui-menu-item> ` ;
220- }
221-
222- // Render items if loading is done and no error occurred
223- return this .renderItems (this ._items );
224- }
225- }
226-
227- export { MyMenuItems as element };
228-
229- declare global {
230- interface HTMLElementTagNameMap {
231- [elementName ]: MyMenuItems ;
232- }
233- }
234- ```
235- {% endcode %}
236-
237- ## Tree Menu Item
238-
239- ### Manifest
240-
241- ``` json
242- {
243- "type" : " menuItem" ,
244- "kind" : " tree" ,
245- "alias" : " My.TreeMenuItem" ,
246- "name" : " My Tree Menu Item" ,
247- "meta" : {
248- "label" : " My Tree Menu Item" ,
249- "menus" : [" My.Menu" ]
250- }
251- }
252- ```
253-
254149#### Default Element
255150
256151The default element supports rendering a subtree of menu items.
@@ -282,14 +177,21 @@ To add a menu item to an existing menu, use the `meta.menus` property.
282177{% code title="umbraco-package.json" %}
283178``` json
284179{
285- "type" : " menuItem" ,
286- "alias" : " My.MenuItem" ,
287- "name" : " My Menu Item" ,
288- "meta" : {
289- "label" : " My Menu Item" ,
290- "menus" : [" Umb.Menu.Content" ]
291- },
292- "element" : " menu-items.js"
180+ "$schema" : " ../../umbraco-package-schema.json" ,
181+ "name" : " My Package" ,
182+ "version" : " 0.1.0" ,
183+ "extensions" : [
184+ {
185+ "type" : " menuItem" ,
186+ "alias" : " My.MenuItem" ,
187+ "name" : " My Menu Item" ,
188+ "meta" : {
189+ "label" : " My Menu Item" ,
190+ "menus" : [" Umb.Menu.Content" ]
191+ },
192+ "element" : " menu-items.js"
193+ }
194+ ]
293195}
294196```
295197{% endcode %}
0 commit comments