8

I am trying to load dynamic input values for a drop down field in ckeditor:

As you can see below when pressing the button no values are loaded in the drop-down:

enter image description here

I would like to have loaded the following values in my drop-down(which should be matched by the reged in the onLoad function):

{{ $slot }}
{{$example }}
{{ $Product2}}
{{$category1 }}

As the snippet does not run on stack-snippets I put a fully working replication of the problem on codepen. See the following link: https://codepen.io/anon/pen/NBXObP

My plugin code looks like the following:

var selectedList = []

CKEDITOR.replace("editor", {
  extraPlugins: "insertData"
});

CKEDITOR.plugins.add( 'insertData', {

    icons: '',
    init: function( editor ) {

        editor.addCommand( 'insertData', new CKEDITOR.dialogCommand( 'insertDataDialog' ) );
        editor.ui.addButton( 'InsertData', {
            label: 'Insert InsertData',
            command: 'insertData',
            toolbar: 'insert'
        });

        if ( editor.contextMenu ) {
            editor.addMenuGroup( 'insertDataGroup' );
            editor.addMenuItem( 'insertDataItem', {
                label: 'Edit InsertData',
                icon: this.path + 'icons/insertData.png',
                command: 'insertData',
                group: 'insertDataGroup'
            });

            editor.contextMenu.addListener( function( element ) {
                if ( element.getAscendant( 'insertData', true ) ) {
                    return { insertDataItem: CKEDITOR.TRISTATE_OFF };
                }
            });
        }

        CKEDITOR.dialog.add( 'insertDataDialog', function (editor) {
    return {

        // Basic properties of the dialog window: title, minimum size.
        title: 'InsertData Properties',
        minWidth: 400,
        minHeight: 200,

        // Dialog window content definition.
        contents: [{
                // Definition of the Basic Settings dialog tab (page).
                id: 'tab-basic',
                label: 'Basic Settings',

                // The tab content.
                elements: [{
                        // Text input field for the insertData text.
                        type: 'select',
                        id: 'insertData',
                        label: 'Element',
                        items: selectedList,
                        'default': '',

                        onLoad: function (widget) {
                            var text = CKEDITOR.instances.editor.getData();
                            var selectedList = text.match(/{{\s*\$\w+\s*}}/g)
                            console.log("text: " + text)
                            console.log("selectedList: " + selectedList)
                        },

                        onChange: function (api) {
                            alert('Current value: ' + this.getValue());
                        }
                    },
                    {
                        type: 'text',
                        id: 'title',
                        label: 'InsertDatas',
                        validate: CKEDITOR.dialog.validate.notEmpty("InsertDatas field cannot be empty."),

                        setup: function (element) {
                            this.setValue(element.getAttribute("title"));
                        },

                        commit: function (element) {
                            element.setAttribute("title", this.getValue());
                        }
                    }

                ]
            },
        ],

        onShow: function () {

            var selection = editor.getSelection();
            var element = selection.getStartElement();

            if (element)
                element = element.getAscendant('insertData', true);

            if (!element || element.getName() != 'insertData') {
                element = editor.document.createElement('insertData');

                this.insertMode = true;
            } else
                this.insertMode = false;

            this.element = element;
                this.setupContent(this.element);
        },

        onOk: function () {
            var insertData = this.element;

            this.commitContent(insertData);
            if (this.insertMode)
                editor.insertElement(insertData);
        }
    };
});
    }
});

Why doesn`t the fields NOT load in the drop-down?

I appreciate your replies!

Carol.Kar
  • 4,581
  • 36
  • 131
  • 264

1 Answers1

4

You forgot to call .add() in your onLoad callback for the plugin dialog select:

selectedList.forEach((item) => {
    this.add(item);
});

or if ES6 is not available:

var _self = this;
selectedList.forEach(function(item) {
    _self.add(item);
});

Modified codepen: https://codepen.io/anon/pen/pZaVXz?editors=1010

Joseph Marikle
  • 76,418
  • 17
  • 112
  • 129
  • Thx for your fast reply! However, if I add another element in the editors content field such as `{{ $test }}` this does not get shown in the drop-down list. – Carol.Kar Jul 31 '18 at 18:29
  • 1
    @Anna.Klee That's because `onLoad` only gets executed once when the dialog is generated. You should instead use `onShow`, which runs every time the dialog is opened. This will introduce a new problem. You'll now have the list constantly growing every time you open the dialog. Because you want to reevaluate it every time anyway, you should then use `_self.clear();` before adding the items in the `onShow` method. I've updated the codepen to reflect this. – Joseph Marikle Jul 31 '18 at 18:34
  • 1
    [`onShow`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_dialog_definition_select.html#property-onShow) is documented in the [CKEDITOR.dialog.definition.select](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_dialog_definition_select.html) documentation. – Joseph Marikle Jul 31 '18 at 18:37
  • Thx for your fast reply! There is one more thing with the drop-down. Each occurance should be unique, so if there are 2 occurances in the content-editor of `{{ $slot }} only 1 should be shown in the drop-down. – Carol.Kar Jul 31 '18 at 18:44
  • 1
    @Anna.Klee there are multiple ways to [dedupe your data](https://stackoverflow.com/questions/1960473/get-all-unique-values-in-a-javascript-array-remove-duplicates), but general sanitation might be in order anyway. You should probably remove the extra whitespace that doesn't change the parsed value, standardize case, etc. Either way, all that can be done in your `onShow` method. – Joseph Marikle Jul 31 '18 at 18:50