Chunk Property File Picker

Summary

When creating a Property on a chunk, if I set the property’s type to “File”, the value is a textfield. How can I make it a file picker? I’ve tried creating a plugin (see Notes below) to inject a file picker when editing the chunk properties in the Manager and attaching it to the OnManagerPageBeforeRender event but that didn’t work.

Step to reproduce

  1. Go to Elements > Chunks and create or edit a chunk.
  2. Click the Properties tab, then Create Property (make sure the Default Properties are unlocked).
  3. Add a Name and select File for the Type
  4. Click Done and then Save.

Observed behavior

When trying to add a file to the new property, the value remains a textfield.

Expected behavior

The new property’s value should be a file picker.

Environment

  • MODX Revolution 3.0.5-pl (traditional)
  • MySQL 8.0.39-30
  • PHP Version 8.3.14

Notes

This is the plugin that I created (well, let’s be honest, ChatGPT created). Is this code wrong, or do I need to approach this problem from another angle? I don’t want to create a TV, System Setting, or Context Setting for this, I’d like to select a file directly from my Chunk’s Properties.

<?php
// Run only on the chunk editing page
if ($modx->controller->config['controller'] === 'element/chunk/update') {
  $modx->regClientStartupHTMLBlock('
    <script>
      Ext.onReady(function() {
        // Enhance the Properties Grid
        Ext.getCmp("modx-grid-properties").on("afteredit", function(e) {
          if (e.field === "type" && e.value === "file") {
            setTimeout(() => attachFilePickerToField(e.record.id), 50);
          }
        });

        // Enhance the "Create/Edit Property" modal
        Ext.getCmp("modx-uep").on("show", function() {
          const typeField = Ext.getCmp("modx-uep-type");
          if (typeField.getValue() === "file") {
            attachFilePickerToModal();
          }
        });

        // Attach the file picker to the appropriate field
        function attachFilePickerToField(fieldId) {
          const inputField = document.querySelector(`#${fieldId} .x-form-field`);
          if (inputField && !inputField.nextSibling) {
            const filePickerButton = document.createElement("button");
            filePickerButton.textContent = "Select File";
            filePickerButton.type = "button";
            filePickerButton.style.marginLeft = "10px";
            filePickerButton.onclick = () => openMediaBrowser(inputField);
            inputField.parentNode.appendChild(filePickerButton);
          }
        }

        function attachFilePickerToModal() {
          const modalInputField = document.querySelector("#modx-uep-value");
          if (modalInputField && !modalInputField.nextSibling) {
            const filePickerButton = document.createElement("button");
            filePickerButton.textContent = "Select File";
            filePickerButton.type = "button";
            filePickerButton.style.marginLeft = "10px";
            filePickerButton.onclick = () => openMediaBrowser(modalInputField);
            modalInputField.parentNode.appendChild(filePickerButton);
          }
        }

        // Open the MODX Media Browser and set the selected file path
        function openMediaBrowser(inputField) {
          MODx.load({
            xtype: "modx-browser",
            multiple: false,
            source: MODx.config.default_media_source || 1,
            listeners: {
              select: function(data) {
                inputField.value = data.fullRelativeUrl;
              }
            }
          }).show();
        }
      });
    </script>
  ');
}