Toolbelt.Blazor.HotKeys icon indicating copy to clipboard operation
Toolbelt.Blazor.HotKeys copied to clipboard

Update binding before invoking hot key? (Blazor Server)

Open MisterGoodcat opened this issue 4 years ago • 3 comments
trafficstars

Hi. I would think that a typical use case is to enable a hot key like ctrl+s to quickly allow the user to save changes. With the AllowedIn argument you can enable this even when the focus is set to an input field:

HotKeys.CreateContext().Add(ModKeys.Ctrl, Keys.S, Save, "Save.", AllowIn.Input | AllowIn.NonTextInput | AllowIn.TextArea);

Good. However, the default behavior for Blazor (Server) is to only update a two-way binding when the focus of an input is lost. Meaning: when the hot key is invoked, the current change to the bound field is not yet applied, resulting in outdated data.

How can we force a binding update, without switching the binding to update on key press (unreasonable for many situations)? Maybe we should have the option to let the JS part of your library force a blur?

MisterGoodcat avatar Jul 19 '21 20:07 MisterGoodcat

@MisterGoodcat

Thank you for that proposal!

Maybe we should have the option to let the JS part of your library force a blur?

That might be a good idea, I think, but doing that may not be the area of responsibility of this package.

Maybe as you already know, I may recommend you to use @bind:event="oninput" at first.

But if we can't use @bind:event="oninput" for this scenario, as you said, we have to fire an onchange event manually with small JavaScript code, I think.

I implemented the sample code of this topic.
You can try it out on the live demo site that's URL is below.

  • https://jsakamoto.github.io/Toolbelt.Blazor.HotKeys/save-text

Please see also the following commit.

  • https://github.com/jsakamoto/Toolbelt.Blazor.HotKeys/commit/23d292d4fe4206a7870b077198855a273cc6a871

I'll be keeping to consider about that idea you proposed, but the above is my opinion at this time.

I hope this determination makes sense.

jsakamoto avatar Jul 22 '21 12:07 jsakamoto

The JavaScript helper sounds like a good solution for me. Using oninput for the binding is not feasible in my scenario, because I'm moving back and forth larger amounts of text that are pre-processed when changed (think: markdown editor). Thanks again!

MisterGoodcat avatar Jul 22 '21 20:07 MisterGoodcat

@MisterGoodcat: this is how I have done it in javascript:

document.body.addEventListener('keydown', e => {
    //save on CTRL+S
    if (e.ctrlKey && e.key === 's') {
        e.preventDefault();
        var element = document.activeElement;
        if (element.matches('input, textarea')) {
            element.blur();
            element.focus();
        }
        let form = element.closest('form');
        form && setTimeout(() => {
            form.dispatchEvent(new SubmitEvent('submit', { submitter: form }));
        }, 1);
    };
});

however, you might invoke blur/focus from your Save method (HotKeyEntry action):

const MyApp = {
    updateBinding() {
        var element = document.activeElement;
        if (element.matches('input, textarea')) {
            element.blur();
            element.focus();
        }
    }
}
async Task Save() {
   await JSRuntime.InvokeAsync('MyApp.updateBinding');   
}

Liero avatar Dec 02 '21 11:12 Liero