Add/Remove plugins dynamically without destroy the editor
📝 Provide a description of the new feature
What is the expected behavior of the proposed feature?
Context: I'd like to swap my editor from collaborative editing enabled and disabled without destroying the editor.
The same situation for inline-comments, i'd like to show comments without connect to RealTimeCollaborativeComments and enable it only if user click over the editor, is there any way to do that?
How i did for collaborative editing? I show my post as readOnly mode and with some user click to edit a post, i destroy my editor instance and re-create a new one with collaborative editing enabled - it doesn't seem me to be right.
What do you guys think of creating a feature for dynamically enable/disable some plugin without destroy ckeditor instance?
If you'd like to see this feature implemented, add a 👍 reaction to this post.
Thanks for sharing your feedback.
What do you guys think of creating a feature for dynamically enable/disable some plugin without destroy
ckeditorinstance?
This is very case-dependent. For most plugins, these related to the content (tables, lists, etc.), it doesn't make sense. What should happen if you suddenly disable tables? :).
This question may be legit in the context of connecting to real-time editing features. We would have to gather more feedback, understand people's use cases, and see if it is popular need, or if it solves some general problem, before committing resources to it.
At this moment, I assume that this is technically default. Maybe achievable through some hacks and delaying some initializations that happen in the plugins, but I give it maybe 30% chance of success, depending on what UX you'd want to achieve.
My question for now is: what is your use case from business point of view, what UX you want to achieve, what scenario you want to solve? I understand technical problem but I'd like to understand your need better.
@scofalik thanks for answer! our scenario it's:
We have multiple instances of Ckeditor, and thinking about performance and cost we just enable the real-time editing if user click on edit post. When user click on edit post we destroy ckeditor instance (readOnly mode) and create a new one using real time editing.
The same situation for inline-comments, we are looking one way to just display comments without connecting to ckeditor cloud and if user click on edit we connect to real time feature.
Why we want to avoid destroy/create instance?
- Sometimes it takes too much time to render
ckeditorinstance again. - User experience it's not good, because the editor blinks when we are recreating it.
Thanks for sharing your case. I understand your problems.
I have additional question. Why did you decide to display the content as an editor in read-only state instead of simply displaying HTML? I don't say this is a bad idea, we sometimes recommend that, but I wonder what are your needs specifically? Most probably handlings comments (markers and balloons), maybe some styling issues? Or was the idea to make the content editable without UX quirks (blinking?) the main factor?
@scofalik that it's a good question! I was trying to display Ckeditor data as a simple HTML instead of creating an instance to show in readOnly mode.
And yes for comments it may have a limitation, because I wouldn't be able to show comments in readOnly mode.
I've tried to use editor.getData() and preview it into some <div [innerHTML]></div>, but i had some issues to render plugins that use figure like tables, images and also it lost styles.
Examples:
- You can see bellow the first data it's a
ckeditorinstance and the second one I tried to render only the HTML:
Result: It didn't render the table and also lost the alignment of the image.

Did you see https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/content-styles.html? I believe it will guide you how to display the content.
@Reinmar thank you for the link. That will be helpful for us
@scofalik we appreciate your response. My colleague DiegoASanches and I have been working hard on ckeditor integration for the past few months.
Why did you decide to display the content as an editor in read-only state instead of simply displaying HTML?
An excellent question 😁 Your guesses are correct
- comments only mode ui
- styling inconsistencies (which we could put some effort in fixing)
- wrapping images in links using editing downcast - https://github.com/ckeditor/ckeditor5/issues/702
I think we can work around all this for now, but eventually we will need to render read-only content as raw html, with some lightweight ui for comments only mode. The editor hasn't performed well rendering several documents at once in readonly mode - there's a lot of overhead with upcast/downcast and rendering toolbar items (even though we hide them).
We'd love to collaborate on this issue with the team. We have a few interesting use cases that would be great to run by you.
The comments issue (comments not possible to be interacted with) is certainly valid and we will track the need for solving it.
@Reinmar already gave you a link that should help you mitigate styles inconsistency problems. Extra fine-tuning will be on you.
Not sure about the image links, maybe again @Reinmar will be able to help you.
Finally, when it comes to comments. You need two things:
- Keep comment highlights in the document data HTML so they can be shown outside the editor.
- Attach comments UI to these highlights even if the editor is not initalized.
For 1., we have such feature for track changes but we don't have for comments. I can give you a snippet that will enable that.
The converters code is a bit complicated because we must overwrite the default conversion and this is not easy currently:
class CustomCommentsConversion extends Plugin {
init() {
this.editor.conversion.for( 'dataDowncast' ).add( dispatcher => {
dispatcher.on( 'addMarker:comment', ( evt, data, conversionApi ) => {
if ( !conversionApi.options.showCommentsHighlights ) {
return;
}
const item = data.item;
if ( !item ) {
// This is for stopping the default conversion.
evt.stop();
return;
}
const id = data.markerName.split( ':' )[ 1 ];
const viewElement = conversionApi.mapper.toViewElement( item );
if (
this.editor.model.schema.isObject( item ) &&
viewElement &&
!viewElement.getCustomProperty( 'widget' ) &&
viewElement.is( 'containerElement' )
) {
conversionApi.writer.addClass( 'ck-comment-marker', viewElement );
conversionApi.writer.setAttribute( 'data-comment', id, viewElement );
}
}, { priority: 'high' } );
} );
this.editor.conversion.for( 'dataDowncast' ).markerToHighlight( {
model: 'comment',
view: ( data, conversionApi ) => {
if ( !conversionApi.options.showCommentsHighlights ) {
return null;
}
const id = data.markerName.split( ':' )[ 1 ];
return {
classes: [ 'ck-comment-marker' ],
attributes: {
'data-comment': id
}
};
},
converterPriority: 'high'
} );
}
}
If you fire editor.getData( { showCommentsHighlights: true } ) you will get something like:
<p>This is a <span class="ck-comment-marker">comment</span>.</p>
<figure class="image ck-comment-marker" data-comment="e86baf30fb3e2becbb36ff41d004c39d6"><img src="..." srcset="..." sizes="100vw" width="224"></figure>
You might need to apply additional styling for these :point_up:.
For 2., I'd propose you trying our comments-outside-editor solution. It will require some effort on your side but maybe it will work correctly and maybe you will be able to solve your issues. In the guide we show how to create comment threads on form elements. In your case it will be easier because you will not need to create new comments, you will only need to load the existing ones. Instead of attaching to form elements, you should look for DOM elements with proper data-comment value and attach to them.
Maybe this will help you.
Thanks for sharing your case. I understand your problems.
I have additional question. Why did you decide to display the content as an editor in read-only state instead of simply displaying HTML? I don't say this is a bad idea, we sometimes recommend that, but I wonder what are your needs specifically? Most probably handlings comments (markers and balloons), maybe some styling issues? Or was the idea to make the content editable without UX quirks (blinking?) the main factor?
Incorrect table style and revision comments cannot be displayed
We are also running into this challenge. We want to display multiple editors on a page; each of them represents a separate document, for domain reasons. Different users may have different sets of paragraphs displayed. But there could be many of them on the page, so we don't want to connect RTC by default to all of them.
Instead, we want to enable real-time collab when a user clicks/activates a paragraph. It would be nice to simply connect or disconnect an editor on the fly.
We use React, so I'm thinking we may use conditional rendering and show completely different editors (one read-only, the other connected to RTC) based on some state?
@DeltekDavid I have two questions regarding your use case:
- Why not simply show a styled document content (HTML) instead of initializing the editor in read-only mode?
- Wouldn't it be confusing for the user that the content of the field that they clicked-to-edit has magically changed (because it was being edited in RTC, but the changes were not showing as the editor was "disconnected")?
Hi @scofalik ,
- Subtle styling differences; it seems easier to use a read-only editor than to try and replicate how CKEditor renders content. Is it easy enough to do with CSS?
- I forgot to mention, we are taking this into account. Suppose Bob and Priyanka are working in the same area. When Bob clicks a paragraph, we'll render a connected CKEditor5 with RTC. Meanwhile, we'll have a websocket connection so that in Priyanka's workspace, the previously-static paragraph is replaced with a live CKEditor. Something to that affect.
The OP's request might not make sense for plug-ins generally, but being able to connect or disconnect an editor on the fly (say, during focus) makes a lot of sense!
- I see. You can use
ck-contentclass on the content to some extend but the differences will be there, as the output HTML differs from the DOM structure inside the editable. Especially if you would want to show comments or tracked changes with annotations. - This makes sense.
The OP's request might not make sense for plug-ins generally, but being able to connect or disconnect an editor on the fly (say, during focus) makes a lot of sense!
I agree. We'd rather provide connecting/disconnecting on demand (or at least connecting on demand) than adding/removing plugins. The latter is simply impossible given the editor strucutre. We would need to introduce a lot of internal mechanisms to make it possible (like de-registering converters or schema rules). It's certainly a bad time investment on our side.
EDIT: BTW. did you try multi-root editor to try to solve your case?
I agree. We'd rather provide connecting/disconnecting on demand (or at least connecting on demand) than adding/removing plugins. The latter is simply impossible given the editor strucutre. We would need to introduce a lot of internal mechanisms to make it possible (like de-registering converters or schema rules). It's certainly a bad time investment on our side.
Of course, that makes sense. But what are the odds of enhancing RTC so that its connectivity can be controlled? No need to destroy the plug-in, just make it more flexible.
EDIT: BTW. did you try multi-root editor to try to solve your case?
Only issue we have with multi-root, is that it requires one single document, correct? In our app, users might be seeing different sets of paragraphs depending on their context. Some will be shared with other users's views, and some won't (e.g. their filter settings). And data-wise, they're not a single document but rather individual entities. (Our app works with individual paragraphs rather than the entire doc, which gets composed and again might vary based on configuration.)
But what are the odds of enhancing RTC so that its connectivity can be controlled?
Not on the roadmap currently, so probably not this year. Sorry :(.
Only issue we have with multi-root, is that it requires one single document, correct? In our app, users might be seeing different sets of paragraphs depending on their context.
I see, in this case multi-root will not be helpful.
I understand, gotta prioritize enhancements. Thanks, though--we will do a selective render in that case.