How to access instance of JavaScript object in another export function in a blazor class library

  blazor-server-side, c#, ckeditor, javascript

I wrote a small razor class library which implements a custom component for CKEditor 5.

Since the editor is displayed via JavaScript, I need to remove it in the DisposeAsync event from the component.

Here is my interop implementation:

export function setup(id, dotNetReference) {
    var newEditor = null;
    ClassicEditor
        .create(document.querySelector('#ckeditor-' + id), {

            toolbar: {
                items: [
                    '|',
                    'bold',
                    'underline',
                    'italic',
                    'strikethrough',
                    'bulletedList',
                    'numberedList',
                    'fontColor',
                    '|',
                    'heading',
                    'undo',
                    'redo'
                ]
            },
            language: 'de',
            licenseKey: '',


        })
        .then(editor => {
            window.editor = editor;
            console.log(editor);
            editor.model.document.on('change:data', () => {
                let data = editor.getData();

                const el = document.createElement('div');
                el.innerHTML = data;
                if (el.innerText.trim() == '')
                    data = "";



                dotNetReference.invokeMethodAsync('EditorDataChanged', data);
            });
        })
        .catch(error => {
            console.error('Oops, something went wrong!');
            console.error('Please, report the following error on https://github.com/ckeditor/ckeditor5/issues with the build id and the error stack trace:');
            console.warn('Build id: 3qd8y8wn1ree-1342d9v8hd01');
            console.error(error);
        });

}

export function destroy() {

    // I need to call editor.destroy(); here
   
}

As you can see I have two functions to call: destroy() and setup(id, dotNetReference)

Within the setup method my CKEditor instance becomes created. In the .then closure I have my editor instance which I within my destroy() method. However, even if I set my instance in a variable in the script, I don’t get access to it because the variable does not seem to exists in the destroy() method.

When I put this line inside the destory() method

document.querySelector('.ck-editor__editable').ckeditorInstance.destroy();

then it works. However when I have implemented the component two times into a single page then both gets destroyed (which makes sence because both can be identified through the same selector.

This is my CkEditorJsInterop class:

public class CkEditorJsInterop : IAsyncDisposable
    {
        private readonly Lazy<Task<IJSObjectReference>> moduleTask;
        private DotNetObjectReference<InputCkEditor> _reference;


        public CkEditorJsInterop(IJSRuntime jsRuntime)
        {
            moduleTask = new(() => jsRuntime.InvokeAsync<IJSObjectReference>(
               "import", "./_content/CKEditor/ckeditor.js").AsTask());
        }

        public async ValueTask InitAsync(Guid id, DotNetObjectReference<InputCkEditor> reference)
        {
            _reference = reference;
            var module = await moduleTask.Value;
            string newId = id.ToString();
            await module.InvokeVoidAsync("setup", new object[] { newId, reference });
        }



        public async ValueTask DisposeAsync()
        {
            if (moduleTask.IsValueCreated)
            {
                var module = await moduleTask.Value;
                await module.InvokeVoidAsync("destroy");
                await module.DisposeAsync();
                


            }
        }
    }

Is there any easy way to get this working as expected?

Source: Ask Javascript Questions

LEAVE A COMMENT