Ckeditor - Load dynamic field values in "select" field
Asked Answered
E

1

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!

Eyebrow answered 28/7, 2018 at 20:11 Comment(0)
R
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

Rourke answered 31/7, 2018 at 18:19 Comment(5)
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.Eyebrow
@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.Rourke
onShow is documented in the CKEDITOR.dialog.definition.select documentation.Rourke
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.Eyebrow
@Anna.Klee there are multiple ways to dedupe your data, 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.Rourke

© 2022 - 2024 — McMap. All rights reserved.