How do I reuse/extend the Umbraco Content Picker in my own property editor?

Goal

Our goal is to use the existing Umbraco Content Picker in Umbraco and extend it ever so slightly that for a picked node, we will make a call to look up the picked content node and get a piece of information from that picked content node as additional information to display, in this case its a mix of a persons name and department that they are from.

Approach

Our thought was for our property editor to wrap the one from the CMS core WebComponent for the built in content picker and then have some additional markup to show what node was picked in order for us to fetch/lookup the data on the picked node.

<umb-property-editor-ui-content-picker 
    .value=${this.value} 
    .config=${this.config} 
    .readonly=${this.readonly}
    @change=${this.#onChange}></umb-property-editor-ui-content-picker>

Why does it not appear in the UI?

So currently it will not render out the button to pick a piece of content.

The weird thing is that if my document type on the same tab contains a normal content picker as well as our custom one, then the UI will render out for our custom one, but it does not honour the configuration of min, max nodes, allowed doctypes and the Dynamic Root Start Node.

What am I missing or overlooked?

Screenshot of missing UI when no other content picker on node

A screenshot of a website interface displays JSON code in a debug section, with a red line and text indicating 'missing pictures in' at the top. (Captioned by AI)

Screenshot of UI appearing when other content picker on node

A screenshot shows the 'Member Role' settings on the Umbraco platform, highlighting the 'Create' button within a rectangular red outline and an arrow pointing towards it. (Captioned by AI)

Manifest.ts

export const manifests: Array<UmbExtensionManifest> = [
    {
        name: "[Consilium] Taxonomy picker with contacts",
        alias: "Consilium.Backoffice.PropertyEditorUi.TaxonomyPickerWithContacts",
        type: "propertyEditorUi",
        js: () => import("./taxonomy-picker-with-contacts/taxonomy-picker-with-contacts.element"),
        meta: {
            group: "Consilium",
            label: "Body taxonomy picker (with related contacts)",
            icon: "icon-page-add",
            propertyEditorSchemaAlias: "Umbraco.MultiNodeTreePicker",
            supportsReadOnly: true,
            settings: {
                properties: [
                    {
                        alias: 'filter',
                        label: 'Allow items of type',
                        description: 'Select the applicable types',
                        propertyEditorUiAlias: 'Umb.PropertyEditorUi.ContentPicker.SourceType',
                    },
                ],
            }
        }
    }
];

taxonomy-picker-with-contacts.element.ts

import { css, customElement, html, LitElement, property } from "@umbraco-cms/backoffice/external/lit";
import { BackofficeCssStyles } from "../../../common/styles/backoffice-css-styles";
import { UmbElementMixin } from "@umbraco-cms/backoffice/element-api";
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor';
import { UmbReferenceByUniqueAndType } from "@umbraco-cms/backoffice/models";
import { UmbChangeEvent } from "@umbraco-cms/backoffice/event";

@customElement('taxonomy-picker-with-contacts')
export default class TaxonomyPickerWithContactsElement extends UmbElementMixin(LitElement) implements UmbPropertyEditorUiElement {
    constructor() {
        super();
    }

    connectedCallback() {
        super.connectedCallback();
    }

    @property({ type: Array })
    value?: UmbReferenceByUniqueAndType[];

    @property()
    config?: any;

    @property({ type: Boolean })
    readonly?: boolean;

    #onChange = (event: CustomEvent) => {
        // console.log('Change event:', event);
        // console.log('Change event TARGET:', event.target);
        
        // Get the new value from the content picker
        // UmbPropertyEditorUIContentPickerElement is not exported by Umbraco, hence an any for now :(
        const target = event.target as any;
        const newValue = target.value;
        
        console.log('New value:', newValue);
        
        // Update our value
        this.value = newValue;
        
        // Dispatch the UmbChangeEvent for Umbraco's property system
        this.dispatchEvent(new UmbChangeEvent());
        
        // Stop the original event from bubbling
        event.stopPropagation();
    }

    render() {
        return html`
            <div class="two-column-layout">
                <div class="picker-column">
                    <div style="border: 2px solid red;">
                        <umb-property-editor-ui-content-picker 
                            .value=${this.value} 
                            .config=${this.config} 
                            .readonly=${this.readonly}
                            @change=${this.#onChange}></umb-property-editor-ui-content-picker>
                    </div>

                    <h2>DEBUG</h2>
                    <umb-code-block language="Value">${JSON.stringify(this.value, null, 2)}</umb-code-block>

                    <umb-code-block language="Config">${JSON.stringify(this.config, null, 2)}</umb-code-block>
                </div>
            
                <div class="contacts-column">
                     <!-- This picker is setup to select only one item, so we can safely access the first item in the array -->
                    <p>You selected: <strong>${this.value?.[0]?.unique ?? ''}</strong></p>
                    
                    <p>Related contacts:</p>
                </div>
            </div>
        `
    }

    static styles = [
        BackofficeCssStyles,
        css`
            .two-column-layout {
                display: flex;
                gap: 1rem;
            }

            .picker-column {
                flex: 3; /* 75% */
            }

            .contacts-column {
                flex: 1; /* 25% */
                padding-top: 10px;
            }
        `
    ];
}

declare global {
    interface HTMLElementTagNameMap {
        'taxonomy-picker-with-contacts': TaxonomyPickerWithContactsElement;
    }
}

hey warren,
i have added a comment on this topic maybe this helps u in some way, this one should do and is very simple. i am currently on holiday so i might not reply back… hope this helps

https://forum.umbraco.com/t/umbraco-15-custom-property-editors-how-to-content-picker-dialog-media-picker-dialog/4388/4 (check for document picker (content picker)

EDIT: eg code
import { UmbInputDocumentElement } from "@umbraco-cms/backoffice/document";

render:

 <umb-input-document
    .selection=${this.#selection}
    @change=${this.#onChangeDocument}>
</umb-input-document>

handler

 #onChangeDocument(event: CustomEvent & { target: UmbInputDocumentElement }) {
    this.showOnPages = event.target.selection?.join(',') ?? null;
    this.dispatchEvent(new UmbPropertyValueChangeEvent());
}

required backing property:

#selection: Array<string> = [];