Create your custom attribute editor (part 6)

Last part of this tutorial will be about enhancing our editor to make it a bit nicer. The idea is to create a property editor to select a file within the repository. We will use the DocumentSelector dialog we wrote here.

We are actually really close of achieving this, we will just hook up the click event of the input field to start the DocumentSelector dialog, and we will also add a Browse button on the right of the input to make it more user-friendly.

First, edit your widget’s template to:

  • add the data-dojo-attach-event attribute on the input
  • add the button (we will also set a size and add the dijitInline class to our input so the button gets next to the input)
<div class="myClass">
<!-- The node that should get the focus should have the focusNode attach point.
     pvr/widget/_Property._createEditorWidget needs this because it wants to set the
     aria-labelledby on it -->
    <input data-dojo-type="ecm.widget.ValidationTextBox" 
           data-dojo-attach-point="inputField,focusNode"
           name="${id}_inputText" id="${id}_inputText"
           class="dijitInline" style="width: 180px;"
           data-dojo-attach-event="onClick:chooseDocument" />
    <span data-dojo-type="ecm.widget.Button" 
          data-dojo-attach-point="browseButton" id="${id}_button"
          ata-dojo-attach-event="onClick:chooseDocument" >Browse</span>
</div>

In our dojo class (MyCustomWidget.js), we only have to add the chooseDocument method, which will start the DocumentSelector dialog and set back the result in the input field once a document is chosen:
(You need to import the DocumentSelector widget we created here)

chooseDocument: function () {
    var dialog = new DocumentSelector({
        "repository": this.repository,
        "filters": null,
        execute: lang.hitch(this, function (item) {
            if (item) {
                this.inputField.set('value', this.getAbsolutePath(item));
            }
        })
    });
    dialog.show();
},

getAbsolutePath: function (item) {
    var res = "", current = item;
    while (current && !current.rootFolder) {
        res = "/" + current.name + res;
        current = current.parent;
    }
    if (res == "") {
        res = "/";
    }
    return res;
}

Now, as you can see, we are expecting a repository field in out widget to instantiate the DocumentSelector dialog. It should be provided when creating the widget, but in our case, the Properties Pane will create it for us, so we can’t do this. So I came up with a small trick, which is to get the repository in our Editor, which knows its Property, whose controller knows its contentClass via its model. There might be a better solution, but I haven’t found it yet and that works :).

Therefore, update your controller (MyCustomController), to add the following postCreate method:

postCreate: function () {
    this.repository = this.property.controller.model.contentClass.repository;
},

This way, at the time the user clicks on the button, the repository will be set. This should be improved to check if none is null of course, and printing a MessageDialog at the time of displaying the DocumentSelector if we couldn’t figure out the repository, but that’s just an example here.

Result at this point should look like this:

ICN_editor_settings_11

And when clicking on the button or on the input field, you should be able to choose a document:
ICN_editor_settings_12

That’s nice, but we are not using the full potential of our DocumentSelector dialog, meaning filters and the select folder option. We will use the Settings feature of ICN property editors to make it easily configurable for administrators.

Add two new settings, as seen in part 5, to let administrators configure filters and if they want users to be able to select a folder or not:

ControlRegistry.editors.editorConfigs[editorId] = {
    label: "My Custom Editor",
    editorClass: MyCustomEditor,
    settings: [
               {
                   name: "filters",
                   controlClass: TextBoxSetting,
                   controlParams: {
                       label: "Filers",
                       help: "Come separated filters"
                   }
               },
               {
                   name: "allowFolder",
                   controlClass: CheckBoxSetting,
                   controlParams: {
                       label: "Allow folder selection",
                       help: "If checked, users can also select folders"
                   }
               }
           ]
};

//register our widget in list of widgets which return single string value (there are other types also)
// see See ecm/model/configuration/ControlRegistry for other possible types
ControlRegistry.editors.mappings.types["string"].single.editorConfigs.push(editorId);

Now we can just use them in our widget when instantiating the DocumentSelector:

chooseDocument: function () {
    var f = []
    if (this.filters) {
        f = this.filters.split(",");
    }
    var dialog = new DocumentSelector({
        "repository": this.repository,
        "filters": f,
        "documentOnly": !this.allowFolder,
        execute: lang.hitch(this, function (item) {
            if (item) {
                this.inputField.set('value', this.getAbsolutePath(item));
            }
        })
    });
    dialog.show();
},

Go to the Entry Template Designer tool, and you should see your two settings:

ICN_editor_settings_13

Set some filters, then go try to add a document to check if they are applied:

ICN_editor_settings_14

As you can see, we can now only choose dita or ditamap as configured. And here is a nice DocumentSelectorEditor you can configure easily!

1 thought on “Create your custom attribute editor (part 6)

  1. Adrian

    I’ve implemented Custom Property Editors only for Single value properties. Now we have a requirement to implement an editor with a list of values, so in essence a Custom Property Editor for multivalue Properties. Unfortuantely I’m unable to find any materials or examples on this topic, what classes to use, which classes to extend. Could You please share an example project to see the basics?

    Reply

Leave a Reply to Adrian Cancel reply