Creating your own UI extension points in Umbraco v14 – Part 4: Interchangeable Elements

Creating your own UI extension points in Umbraco v14 – Part 4: Interchangeable Elements

In the last post we looked at how we can swap out our “quick action” button behavior whenever a button is clicked.

In this post we’ll take a look at how we could allow someone to completely replace the button element with some other user control.

Element Extensions

To allow our actions to support a interchangeable elements we first need to update our manifest definition again.

export interface ManifestQuickAction extends ManifestElementAndApi<QuickActionElement, QuickActionApi> {
type: quickAction;
meta: MetaQuickAction;
}

export interface QuickActionElement extends UmbControllerHostElement {
manifest: UcManifestEntityQuickAction;
api?: QuickActionApi;
}

Here again we swap out the base interface and now extend from ManifestElementAndApi<>. We also define a QuickActionElement interface which lays out the required properties that any element used as a quick action must support. This interface, along with our previously defined API interface, are passed to the ManifestElementAndApi<> interface as generic arguments.

If we take a look at the ManifestElementAndApi<> interface we can see that our manifest now supports a couple of extra properties.

export interface ManifestElementAndApi<ElementType, ApiType> extends ManifestBase {
element?: ElementLoaderProperty<ElementType>;
elementName?: string;

}

Default Element Updates

With our element interface defined, we can go back to our default button implementation and ensure this now implements our required interface.

@customElement(quick-action)
export class QuickActionElement extends UmbElementMixin(LitElement)
implements QuickActionElement {

@property({ type: Object, attribute: false })
manifest!: ManifestQuickAction;

@property({ type: Object, attribute: false })
api?: QuickActionApi;

#onClick(e: Event) {
this.api?.execute();
}

render() {
return html`<uui-button
look=
${this.manifest.meta.look ?? secondary}
@click=
${this.#onClick}>
${this.manifest.meta.label}
</uui-button>`

}
}

export default QuickActionElement;

declare global {
interface HTMLElementTagNameMap {
quick-action: QuickActionElement;
}
}

Overriding the Default Element

With everything configured developers can now override the default button element by firstly creating their own component that implements our interface.

@customElement(my-quick-action)
export class MyQuickActionElement extends UmbElementMixin(LitElement)
implements QuickActionElement {

@property({ type: Object, attribute: false })
manifest!: ManifestQuickAction;

@property({ type: Object, attribute: false })
api?: QuickActionApi;

#onClick(e: Event) {
this.api?.execute();
}

render() {
return html`RENDER YOUR COMPONENT HERE`
}
}

export default MyQuickActionElement;

declare global {
interface HTMLElementTagNameMap {
my-quick-action: MyQuickActionElement;
}
}

Then updating the manifest to use this component instead.

export const quickActionManifests: ManifestQuickAction[] = [
{
type: quickAction,
alias: Mb.QuickAction.SendEmail,
name: Send Email Quick Action,
weight: 200,
element: MyQuickActionElement,
api: SendEmailQuickActionApi,
meta: {
label: Send Email,
look: primary
}
},
{
type: quickAction,
alias: Mb.QuickAction.ChangeStatus,
name: Change Status Quick Action,
weight: 100,
element: MyQuickActionElement,
api: ChangeStatusQuickActionApi,
meta: {
label: Change Status
}
}
]

What’s next?

In this post we’ve looked out how to allow developers to override the default element of an extension.

In the next post we’ll take a look at how we can reduce some repetition in our manifest definitions by creating reusable ‘kinds’.

Until then 👋

Leave a Reply

Your email address will not be published. Required fields are marked *