Search code examples
ckeditor

Passing dialog data to CKEditor widget template


I have created a CKEditor widget and an associated dialog with a few fields.

I would like to directly place the values of these fields into the generated template of the widget. I cannot seem to figure out how this work though.

Dialog field:

{
  id: 'message',
  type: 'textarea',
  label: 'Message',
  'default': '',
  setup: function( widget ) {
    this.setValue( widget.data.message );
  },
  commit: function( widget ) {
    widget.setData( 'message', this.getValue() );
  }
}

plugin template:

init: function( editor ) {
    CKEDITOR.dialog.add( 'note', this.path + 'dialogs/note.js' );

    editor.widgets.add( 'note', {

      button: 'Create a note',

      dialog: 'note',

      template:
        '<div class="admonition note">' +
        '<p class="first admonition-title">Title</p>' +
        '<p class="last">Message</p>' +
        '</div>',
....

Solution

  • I was able to achieve what I wanted by directly manipulating the DOM due to the fact that widget templates are immutable.

    The Widget API can help us here with the usage of parts, init, edit, data and the methods setData and setHtml.

    CKEDITOR.plugins.add('note',{
      ...
      requires: 'widget,dialog',
      init: function(editor) {
        const html =
          '<div class="note">' +
          '<p class="note-title">Note</p>' +
          '<p class="note-message">Message</p>' +
          '</div>';
        const path = this.path;
        CKEDITOR.dialog.add('note',path + 'dialogs/note.js' );
        editor.widgets.add( 'note', {
          template: html,
          parts: {
            note: 'div.note',
            message: 'p.note-message'
          },
          upcast: function(element) {
            return element.name === 'div' && element.hasClass( 'note' );
          },
          init: function () {
            // called when loading the widget
            this.setData('message', this.parts.message.getHtml());
          },
          edit: function() {
            // called when opening the dialog
            const message = this.parts.message.getHtml();
            if (message !== this.data.message) {
              this.setData('message', message);
            }
          },
          data: function() {
            // called when you save the dialog
            this.parts.message.setHtml(this.data.message);
          }
        });
      }
    }