In my Blazor Web App with .NET 9, I was trying to monitor if the editor loses focus. While I can monitor the editor itself, I have no idea how to properly integrate QuillJS's hasFocus event with a C# approach to handle this. For this reason, I've decided to mimic the behavior of the @onblur event in a <div id="editor"></div>, assuming it's possible...
My initial attempt was to see if @onblur would work, but it didn't:
<div id="editor" @onblur="FormatOnBlurQuill"></div>
@code {
private void FormatOnBlurQuill(FocusEventArgs e)
{
Console.WriteLine("Test focus blur"); // not working
}
}
I suspected that this wasn't the same as an InputText or a related form field that can handle @onblur events.
However, I tried to see if I could get the editor's focus status this way:
window.previewContent = function () {
const quill = new Quill('#editor', {
modules: {
toolbar: '#toolbar-container'
},
placeholder: 'Compose a product description here...',
theme: 'snow'
});
window.quillEditor = quill;
};
window.getQuillFocusState = function () {
if (window.quillEditor) {
return window.quillEditor.hasFocus();
}
}
@inject IJSRuntime JS
@* Client-side code here... *@
@code {
private async Task SomeMethod()
{
await JS.InvokeVoidAsync("previewContent");
bool isQuillFocused = await JS.InvokeAsync<bool>("getQuillFocusState");
Console.WriteLine($"Is quill focused: {isQuillFocused}"); // Is quill focused: False
}
}
I'm not familiar with how to handle events with JavaScript in a Blazor Web App to continuously monitor the focus status of the QuillJS editor.
My question for this context:
I came up with two workarounds (i.e., on the JavaScript side codebase), each with a different concept that requires fine-tuning depending on my use case. However, these two workarounds share the same server-side concept, which relies on the DotNetObjectReference Class and Microsoft.JSInterop.JSInvokableAttribute.
Here's the server-side concept (refactored version):
@inject IJSRuntime JS
@* Client-side code here... *@
@code {
private bool quillFocusState;
private async Task SomeMethod()
{
await JS.InvokeVoidAsync("previewContent");
var dotNetObjRef = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("getQuillFocusState", dotNetObjRef);
}
[JSInvokable]
public void QuillStateFocusChanged(bool focused)
{
quillFocusState = focused;
Console.WriteLine($"Quill focus state changed: {quillFocusState}"); // to test
StateHasChanged(); // Depending on my use case...
}
}
Here are the two sets of workarounds (i.e., on the JavaScript side codebase):
addEventListenerwindow.getQuillFocusState = function (dotNetObjRef) {
if (window.quillEditor) {
window.quillEditor.root.addEventListener('focus', () => {
dotNetObjRef.invokeMethodAsync('QuillStateFocusChanged', true);
});
window.quillEditor.root.addEventListener('blur', () => {
dotNetObjRef.invokeMethodAsync('QuillStateFocusChanged', false);
});
}
}
The code above works as expected but has some focus state glitches. I need to fine-tune this snippet because it conflicts with another addEventListener call.
window.getQuillFocusState = function (dotNetObjRef) {
if (window.quillEditor) {
window.quillEditor.on('selection-change', (range, oldRange, source) => {
if (range) {
if (range.length == 0) {
console.log('User cursor is on', range.index); // to test
} else {
const text = quill.getText(range.index, range.length);
console.log('User has highlighted', text); // to test
}
dotNetObjRef.invokeMethodAsync('QuillStateFocusChanged', true); // actual integration
} else {
console.log('Cursor not in the editor'); // to test
dotNetObjRef.invokeMethodAsync('QuillStateFocusChanged', false); // actual integration
}
});
}
}
The only challenge with the code snippet is that I need to enforce a reasonable execution delay before executing the submit button, for example. This algorithm is responsible for handling customized validation messages (or any other server-side processes) whenever the QuillJS editor's focus changes.