CKEditor 5 – get editor instances
Asked Answered
S

4

18

I am migrating from CKEditor 4.7 to 5.

In CKE4, I would do something like this: CKEDITOR.replace('text_area'); and then in another JS function I could get the data by CKEDITOR.instances.text_area.getData().

But it doesn't appear that CKE5 has a function ClassicEditor.instances or something analogous.

I know I can store the editor instance as a global JS variable, but the code I am working with creates the editors in a general function, so I can't just create a global variable since I don't know the name of the editor a priori. There can also be several editors active on the screen at the same time.

Is there no analog in CKE5 to the old instances that would allow me to get an editor instance from just the id of the textarea it replaced?

I guess I could create my own global array to hold the editor instances, but I would rather not if there is something built in and better-supported

Sauerbraten answered 2/2, 2018 at 4:3 Comment(0)
H
30

This question was already answered in How to get data from CKEDITOR5 instance, but let's consider here a case with more than one editor instance.

I guess I could create my own global array to hold the editor instances, but I would rather not if there is something built in and better-supported

There's no repository of editor instances. We could add it but we don't feel that this is an essential feature. It's actually something that people got used to in CKEditor 4 so they never thought and learned how to manage their editors by themselves.

Also, the reason why there's no single repository of instances is that there's no central singleton object at all. You may implement multiple editor classes and they don't have to know about each other. To come up with a repository, we'd need to centralise these things again.

So, as you pointed out yourself, a simple way to store all instances would be by having a global (global within your app or module, not necessarily a "global JS variable") map of these instances.

The keys to these instances can be the ids of elements on which you initialised editors:

const editors = {}; // You can also use new Map() if you use ES6.

function createEditor( elementId ) {
    return ClassicEditor
        .create( document.getElementById( elementId ) )
        .then( editor => {
            editors[ elementId ] = editor;
        } )
        .catch( err => console.error( err.stack ) );
}

// In real life, you may also need to take care of the returned promises.
createEditor( 'editor1' );
createEditor( 'editor2' );

// Later on:
editors.editor1.getData();

What if you don't assign ids to elements in the DOM? If you use ES6, then it's not a problem. Elements, like other objects, can be keys of a map.

const editors = new Map();

function createEditor( elementToReplace ) {
    return ClassicEditor
        .create( elementToReplace )
        .then( editor => {
            editors.set( elementToReplace, editor );
        } )
        .catch( err => console.error( err.stack ) );
}

// In real life, you may also need to take care of the returned promises.
createEditor( textarea1 );
createEditor( textarea2 );

// Later on:
editors.get( textarea1 ).getData();

If you can't use ES6, then you'd need to do a bit more – e.g. dynamically assign some data-editor-id attributes to elements on which you create the editors.

Hajji answered 8/2, 2018 at 9:56 Comment(2)
Thank you for the thorough explanation! We're not using ES6 yet, so it looks like your first recommended implementation is exactly what I need. Many thanks!Sauerbraten
Do editors ever get removed from the editors Map? Wouldn't this create a memory leak in a SPA?Wyman
S
11

It's not the first time I'm trying to remind myself how to access the CKEditor instance on a production website having just access to the DOM via the developer console, so a reminder for myself ;)

https://ckeditor.com/docs/ckeditor5/latest/builds/guides/faq.html#how-to-get-the-editor-instance-object-from-the-dom-element

It's possible to access the editor instance using the ckeditorInstance property which is available on the contenteditable element that CKEditor 5 is using. You can access this DOM element via e.g. the .ck-editor__editable class.

// A reference to the editor editable element in the DOM.
const domEditableElement = document.querySelector( '.ck-editor__editable' );
    
// Get the editor instance from the editable element.
const editorInstance = domEditableElement.ckeditorInstance;
    
// Now you can use the editor instance API.
editorInstance.setData( '<p>Hello world!<p>' );
Sarad answered 27/5, 2020 at 11:57 Comment(1)
As of April 2022, the correct doc link is: ckeditor.com/docs/ckeditor5/latest/support/…Lutestring
H
3

I wanted to add that if you're looking to achieve this in Drupal 9.5+ that Drupal does create a Map of these for us. Drupal.CKEditor5Instances will return a Map with all the editors.

You can then achieve the same results Drupal.CKEditor5Instances.get("{editorId}").getData().

Highlander answered 28/2, 2023 at 18:46 Comment(0)
C
0

Running multiple copies of the editor using jQuery and a class selector:

$( '.editor' ).each( function() {
    InlineEditor
        .create( this )
        .catch( error => {
            console.error( error );
        } );
});
Cur answered 25/9, 2021 at 16:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.