The component I wrote is as follows.
This Blazor component integrates CKEditor into a Blazor project using JavaScript interop (IJSRuntime).
A simple element is defined with an id that defaults to “editor”, but the EditorId can be passed as a parameter to allow multiple CKEditor instances.
Value: The current value of the editor, bound to the content in CKEditor.
ValueChanged: An EventCallback that notifies the parent component of content changes in CKEditor.
EditorId: The id of the editor, which defaults to “editor”, used for JavaScript interop to link CKEditor to the right element.
@using Microsoft.JSInterop
<textarea id="@EditorId"></textarea>
@code {
[Inject] private IJSRuntime JS { get; set; }
[Parameter] public string Value { get; set; }
[Parameter] public EventCallback<string> ValueChanged { get; set; }
[Parameter] public string EditorId { get; set; } = "editor";
private DotNetObjectReference<CkEditor> _objRef;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_objRef = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("initializeCkEditor", EditorId, _objRef);
}
}
[JSInvokable]
public async Task UpdateValue()
{
var content = await JS.InvokeAsync<string>("getEditorContent", EditorId);
if (content != Value)
{
Value = content;
await ValueChanged.InvokeAsync(Value);
}
}
public void Dispose()
{
_objRef?.Dispose();
}
}
Also, the javascript code is according to the following code
window.initializeCkEditor = (editorId, dotNetObject) => {
if (CKEDITOR.instances[editorId]) {
CKEDITOR.instances[editorId].destroy();
}
CKEDITOR.replace(editorId);
CKEDITOR.instances[editorId].on('change', function () {
dotNetObject.invokeMethodAsync('UpdateValue');
});
};
window.getEditorContent = (editorId) => {
if (CKEDITOR.instances[editorId]) {
return CKEDITOR.instances[editorId].getData();
}
return '';
};
window.setEditorContent = (editorId, content) => {
const interval = setInterval(() => {
if (CKEDITOR.instances[editorId]) {
CKEDITOR.instances[editorId].setData(content);
clearInterval(interval);
}
}, 100);
};
Sometimes when loading the component page it doesn’t work properly.