Opening a Content Picker modal from a Custom Property Editor

Hello.

I am building a Custom Property Editor where by the user can select items from the content tree.

I’m struggling to understand and find what things I should even be looking for in the documentation.

When the user clicks a button, I can get the Modal to open, but it doesn’t show me the content tree for the user to select from. This is what I have so far.

const modal = this._modalContext?.open(this, UMB_TREE_PICKER_MODAL, {
    data: {
        hideTreeRoot: true,
        multiple: false
    },
    value: {
        selection: []
    }
} );

Secondly to this (and this is something I am pre-empting), I am wanting to get as much info from the selected item as possible, (i.e. name and id). I have another property editor that opens a media library and that’ll only returns the id and I use “UmbMediaUrlRepository” to get the rest of the information I need.

Thank you in advance,
Rob

Hi,

I think if you use UMB_DOCUMENT_PICKER_MODAL in place of UMB_TREE_PICKER_MODAL you should get the content tree showing up.

Hello @KevinJump . Thank you so much. Not sure how I missed that.

With regards to getting the details. I am having to use “UmbDocumentItemRepository”. to get the details of the item(s) that were selected. I assume this is an ok approach?

E.g

import { UMB_DOCUMENT_PICKER_MODAL, UmbDocumentItemRepository } from '@umbraco-cms/backoffice/document';
#itemRepository = new UmbDocumentItemRepository(this);
modal.onSubmit().then(async (response) => {
    if (!response) return;
    let { data } = await this.#itemRepository.requestItems(
        response.selection
    );
    console.log(data);
});

Thank you again for your help.

hello, I’m struggling with the same thing myself, are you able to share the full ts file please?

Hello @bobbybobbybobbobbob .

Sure. I’ve removed loads of my stuff to simplify it, but this is the basics:

import { LitElement, html, customElement, state, property } from "@umbraco-cms/backoffice/external/lit";
import { UmbElementMixin } from "@umbraco-cms/backoffice/element-api";
import { UmbPropertyValueChangeEvent } from "@umbraco-cms/backoffice/property-editor";
import { UMB_MODAL_MANAGER_CONTEXT, UmbModalManagerContext } from "@umbraco-cms/backoffice/modal";
import { UMB_DOCUMENT_PICKER_MODAL, UmbDocumentItemRepository } from '@umbraco-cms/backoffice/document';

@customElement("item-picker")
export class ItemPicker extends UmbElementMixin(LitElement)
{   
    
    #modalContext?: UmbModalManagerContext;
    #itemRepository = new UmbDocumentItemRepository(this);
    
    _defaults = []

    @state() _value: {};


    // Getters and Setters for the value property.
    @property({ attribute: false })
    get value() {
        return this._value;
    }
    set value(newValue) {
        if (!newValue) {
            
            this._value = this._defaults;

        } else {
            this._value = newValue;

            // Notify Umbraco about the change to value, so it alerts
            // the user if they navigate away from page.
            this.dispatchEvent(new UmbPropertyValueChangeEvent());
        }
    }


    // Constructor
    constructor() {
        super();
        
        this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (_instance) => {
			this.#modalContext = _instance;
		});
    }


    render() {
        return html`
            <button @click=${this._openModal}>Open Modal</button>
        `
    }
    

    /**
     * Open Modal (Document Picker)
     * @param id
     */
    async _openModal() {
        
        const modal = this.#modalContext?.open(
            this,
            UMB_DOCUMENT_PICKER_MODAL,
            {
                data: {
                    hideTreeRoot: true,
                    multiple: true
                },
                value: {
                    selection: []
                }
            }    
        );

        // On modal submit, update the value with the data passed back.
        modal.onSubmit().then(async (response) => {
            if (!response) return;

            let { data } = await this.#itemRepository.requestItems(
                response.selection
            );
            
            console.log(data);
            
        });
    }
}

export {
    ItemPicker as default
};

I hope that helps you with whatever is it you’re doing.

Thanks, I’ll try it out.

Hi, just want to write an update as of v.16 there is a helper method to open modals called umbOpenModal , which makes it a bit simpler to open a modal.

So now the example above can then be boiled down to:

import { LitElement, html, customElement, state, property } from "@umbraco-cms/backoffice/external/lit";
import { UmbElementMixin } from "@umbraco-cms/backoffice/element-api";
import { UmbPropertyValueChangeEvent } from "@umbraco-cms/backoffice/property-editor";
import { umbOpenModal } from "@umbraco-cms/backoffice/modal";
import { UMB_DOCUMENT_PICKER_MODAL, UmbDocumentItemRepository } from '@umbraco-cms/backoffice/document';

@customElement("item-picker")
export class ItemPicker extends UmbElementMixin(LitElement)
{   
    
    #itemRepository = new UmbDocumentItemRepository(this);
    
    _defaults = []

    @state() _value: {};


    // Getters and Setters for the value property.
    @property({ attribute: false })
    get value() {
        return this._value;
    }
    set value(newValue) {
        if (!newValue) {
            
            this._value = this._defaults;

        } else {
            this._value = newValue;

            // Notify Umbraco about the change to value, so it alerts
            // the user if they navigate away from page.
            this.dispatchEvent(new UmbPropertyValueChangeEvent());
        }
    }

    render() {
        return html`
            <button @click=${this._openModal}>Open Modal</button>
        `
    }
    

    /**
     * Open Modal (Document Picker)
     * @param id
     */
    async _openModal() {

        const response = await umbOpenModal(this, UMB_DOCUMENT_PICKER_MODAL,  {
                data: {
                    hideTreeRoot: true,
                    multiple: true
                },
                value: {
                    selection: []
                }
          }).catch(() => undefined);
      
          if (!response) return;

          let { data } = await this.#itemRepository.requestItems(
              response.selection
          );
          
          console.log(data);
            
    }
}

export {
    ItemPicker as default
};
2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.