Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ The manifest can also be written in TypeScript.
For this TypeScript example we used a [Backoffice Entry Point](../../extending-overview/extension-types/backoffice-entry-point.md) extension to register the manifests.

```typescript
import { ManifestMenu } from "@umbraco-cms/backoffice/extension-registry";
import type { ManifestMenu } from '@umbraco-cms/backoffice/menu';

const menuManifest: Array<ManifestMenu> = [
{
Expand All @@ -55,7 +55,7 @@ const menuManifest: Array<ManifestMenu> = [

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

Menu items are the items that appear in the menu.
Menu items are the items that appear in the menu.

## Creating a custom menu items

Expand Down Expand Up @@ -139,10 +139,9 @@ You can fetch the data and render the menu items using the Lit element above. By

{% code title="menu-items.ts" overflow="wrap" lineNumbers="true" %}
```typescript
import { UmbMenuItemElement } from '@umbraco-cms/backoffice/extension-registry';
import type { UmbMenuItemElement } from '@umbraco-cms/backoffice/menu';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { html, TemplateResult } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { html, TemplateResult, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { MyMenuItemResponseModel, MyMenuResource } from '../../../api';

const elementName = 'my-menu-item';
Expand All @@ -151,13 +150,14 @@ const elementName = 'my-menu-item';
class MyMenuItems extends UmbLitElement implements UmbMenuItemElement {
@state()
private _items: MyMenuItemResponseModel[] = []; // Store fetched items

@state()
private _loading: boolean = true; // Track loading state

@state()
private _error: string | null = null; // Track any errors

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

Expand All @@ -178,8 +178,8 @@ class MyMenuItems extends UmbLitElement implements UmbMenuItemElement {
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>`
${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) : ''}
Expand All @@ -189,7 +189,7 @@ class MyMenuItems extends UmbLitElement implements UmbMenuItemElement {
}

// Main render function
render() {
override render() {
if (this._loading) {
return html`<uui-loader></uui-loader>`;
}
Expand All @@ -200,7 +200,7 @@ class MyMenuItems extends UmbLitElement implements UmbMenuItemElement {
}

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

Expand All @@ -212,15 +212,15 @@ declare global {
}
}

```
```
{% endcode %}


## Tree Menu Item

### Manifest

```typescript
```json
// it will be something like this
{
"type": "menuItem",
Expand All @@ -236,9 +236,10 @@ declare global {

#### Default Element

The default element supports rendering a subtree of menu items.

```typescript
// get interface
interface UmbTreeMenuItemElement {}
class UmbMenuItemTreeDefaultElement {}
```

### Adding menu items to an existing menu
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ There are two parts to creating a custom modal:
A modal token is a string that identifies a modal. This is the modal extension alias. It is used to open a modal and is also to set default options for the modal. It should also have a unique alias to avoid conflicts with other modals.

```ts
import { UmbModalToken } from "@umbraco-cms/backoffice/modal";
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';

export type MyModalData = {
headline: string;
Expand Down Expand Up @@ -48,15 +48,15 @@ Additionally, the modal element can see its data parameters through the `modalCo

{% code title="my-modal.element.ts" %}
```ts
import { html, LitElement, property, customElement } from "@umbraco-cms/backoffice/external/lit";
import { UmbElementMixin } from "@umbraco-cms/backoffice/element-api";
import type { UmbModalContext } from "@umbraco-cms/backoffice/modal";
import type { MyModalData, MyModalValue } from "./my-modal.token.ts";
import { UmbModalExtensionElement } from "@umbraco-cms/backoffice/extension-registry";
import { customElement, html, property } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbModalExtensionElement } from '@umbraco-cms/backoffice/modal';
import type { UmbModalContext } from '@umbraco-cms/backoffice/modal';
import type { MyModalData, MyModalValue } from './my-modal.token.js';

@customElement('my-dialog')
export default class MyDialogElement
extends UmbElementMixin(LitElement)
extends UmbLitElement
implements UmbModalExtensionElement<MyModalData, MyModalValue> {

@property({ attribute: false })
Expand All @@ -70,14 +70,14 @@ export default class MyDialogElement
}

private _handleSubmit() {
this.modalContext?.updateValue({ myData: "hello world" });
this.modalContext?.updateValue({ myData: 'hello world' });
this.modalContext?.submit();
}

render() {
return html`
<div>
<h1>${this.modalContext?.data.headline ?? "Default headline"}</h1>
<h1>${this.modalContext?.data.headline ?? 'Default headline'}</h1>
<button @click=${this._handleCancel}>Cancel</button>
<button @click=${this._handleSubmit}>Submit</button>
</div>
Expand Down Expand Up @@ -106,14 +106,13 @@ To open the modal, you need to consume the `UmbModalManagerContext` and then use

{% code title="my-element.ts" %}
```ts
import { MY_MODAL_TOKEN } from './my-modal.token';
import { customElement, html } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { MY_MODAL_TOKEN } from './my-modal.token.js';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';

@customElement('my-element')
class MyElement extends UmbElementMixin(LitElement) {
class MyElement extends UmbLitElement {
#modalManagerContext?: typeof UMB_MODAL_MANAGER_CONTEXT.TYPE;

constructor() {
Expand All @@ -124,7 +123,7 @@ class MyElement extends UmbElementMixin(LitElement) {
});
}

render() {
override render() {
return html`
<uui-button look="primary" label="Open modal" @click=${this._openModal}></uui-button>
`;
Expand All @@ -138,5 +137,11 @@ class MyElement extends UmbElementMixin(LitElement) {
});
}
}

declare global {
interface HTMLElementTagNameMap {
'my-element': MyElement;
}
}
```
{% endcode %}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ The manifest can also be written in TypeScript.
For this TypeScript example we used a [Backoffice Entry Point](../backoffice-entry-point.md) extension to register the manifests.

```typescript
import { ManifestSectionView } from "@umbraco-cms/backoffice/extension-registry";
import { ManifestSectionView } from '@umbraco-cms/backoffice/section';

const sectionViews: Array<ManifestSectionView> = [
{
Expand Down Expand Up @@ -83,21 +83,21 @@ Creating the Section View Element using a Lit Element.
**my-section.element.ts:**

```typescript
import { UmbLitElement } from "@umbraco-cms/backoffice/lit-element";
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit';

@customElement('my-sectionview-element')
export class MySectionViewElement extends UmbLitElement {

render() {
override render() {
return html`
<uui-box headline="Sectionview Title goes here">
Sectionview content goes here
</uui-box>
`
}

static override styles = [
static override readonly styles = [
css`
:host {
display: block;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

### Property Editor UI

{% code title="umbraco-package.json" %}

Check warning on line 17 in 15/umbraco-cms/customizing/property-editors/composition/property-editor-ui.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [UmbracoDocs.UmbracoTerms] We prefer 'Umbraco' over 'umbraco.' Raw Output: {"message": "[UmbracoDocs.UmbracoTerms] We prefer 'Umbraco' over 'umbraco.'", "location": {"path": "15/umbraco-cms/customizing/property-editors/composition/property-editor-ui.md", "range": {"start": {"line": 17, "column": 16}}}, "severity": "WARNING"}
```json
{
"type": "propertyEditorUi",
Expand All @@ -29,6 +30,7 @@
}
}
```
{% endcode %}

The Property Editor UI cannot be used for Content Types if no Property Editor Schema is specified in the manifest. However, it can still be utilized to manipulate JSON. A case of that could be a Settings property for another Property Editor UI or Schema.

Expand All @@ -42,6 +44,7 @@

**Manifest**

{% code title="umbraco-package.json" %}

Check warning on line 47 in 15/umbraco-cms/customizing/property-editors/composition/property-editor-ui.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [UmbracoDocs.UmbracoTerms] We prefer 'Umbraco' over 'umbraco.' Raw Output: {"message": "[UmbracoDocs.UmbracoTerms] We prefer 'Umbraco' over 'umbraco.'", "location": {"path": "15/umbraco-cms/customizing/property-editors/composition/property-editor-ui.md", "range": {"start": {"line": 47, "column": 16}}}, "severity": "WARNING"}
```json
{
"type": "propertyEditorUi",
Expand All @@ -68,47 +71,73 @@
},
};
```
{% endcode %}

## The Property Editor UI Element

Inherit the interface, to secure your Element live up to the requirements of this.
Implement the `UmbPropertyEditorUiElement` interface, to secure your Element live up to the requirements of this.

```typescript
// TODO: get interface
interface UmbPropertyEditorUIElement {}
interface UmbPropertyEditorUiElement extends HTMLElement {
name?: string;
value?: unknown;
config?: UmbPropertyEditorConfigCollection;
mandatory?: boolean;
mandatoryMessage?: string;
destroy?: () => void;
}
```

{% hint style="info" %}
The `UmbPropertyEditorUiElement` interface ensures that your Element has the necessary properties and methods to be used as a Property Editor UI Element.

See the [UI API documentation](https://apidocs.umbraco.com/v15/ui-api/interfaces/packages_core_property-editor.UmbPropertyEditorUiElement.html) for more information.
{% endhint %}

**Example with LitElement**

{% code title="my-text-box.ts" lineNumbers="true" %}
```typescript
import { LitElement, html, css, customElement, property } from '@umbraco-cms/backoffice/external/lit';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor';

@customElement('my-text-box')
export default class UmbPropertyEditorUITextBoxElement extends UmbElementMixin(LitElement) {

@property()
value: string | undefined;

@property({ attribute: false })
public config: UmbPropertyEditorConfigCollection | undefined;

private onInput(e: InputEvent) {
this.value = (e.target as HTMLInputElement).value;
this.dispatchEvent(new UmbPropertyValueChangeEvent());
}
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type {
UmbPropertyEditorConfigCollection,
UmbPropertyEditorUiElement,
} from '@umbraco-cms/backoffice/property-editor';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';

@customElement('umb-property-editor-ui-text-box')
export default class UmbPropertyEditorUITextBoxElement extends UmbLitElement implements UmbPropertyEditorUiElement {
@property()
value?: string;

@property({ attribute: false })
config?: UmbPropertyEditorConfigCollection;

#onInput(e: InputEvent) {
this.value = (e.target as HTMLInputElement).value;
this.dispatchEvent(new UmbChangeEvent());
}

override render() {
return html`<uui-input .value=${this.value ?? ''} type="text" @input=${this.#onInput}></uui-input>`;
}

static override readonly styles = [
UmbTextStyles,
css`
uui-input {
width: 100%;
}
`,
];
}

render() {
return html`<uui-input .value=${this.value} type="text" @input=${this.onInput}></uui-input>`;
}

static styles = [
css`
uui-input {
width: 100%;
}
`,
];
declare global {
interface HTMLElementTagNameMap {
'umb-property-editor-ui-text-box': UmbPropertyEditorUITextBoxElement;
}
}
```
{% endcode %}
10 changes: 5 additions & 5 deletions 15/umbraco-cms/tutorials/creating-a-custom-dashboard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,15 @@ Now let's create the web component we need for our property editor. This web com
1. Create a file in the `src` folder with the name `welcome-dashboard.element.ts`
2. In this new file, add the following code:

{% code title="welcome-dashboard.element.ts" lineNumbers="true" %}
{% code title="welcome-dashboard.element.ts" lineNumbers="true" overflow="wrap" %}
```typescript
import { LitElement, css, html, customElement } from "@umbraco-cms/backoffice/external/lit";
import { UmbLitElement } from "@umbraco-cms/backoffice/lit-element";
import { LitElement, css, html, customElement } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';

@customElement('my-welcome-dashboard')
export class MyWelcomeDashboardElement extends UmbLitElement {

render() {
override render() {
return html`
<h1>Welcome Dashboard</h1>
<div>
Expand All @@ -120,7 +120,7 @@ export class MyWelcomeDashboardElement extends UmbLitElement {
`;
}

static styles = [
static override readonly styles = [
css`
:host {
display: block;
Expand Down
Loading
Loading