Is there a way to update a binding variable attached to an Input text Item in Blazor when using Ctrl +V combination keys?

扶醉桌前 提交于 2019-12-11 17:05:15

问题


I have this input which is to capture a phone number. When the user enters a number and press the "Enter" Key the Method "KeyWasPressed" is triggered and some validation happens. this works as expected BUT...

When the user copies and pastes the number from excel, for example, the variable @Phone doesn't updates its value so when the user presses the "Enter" key the validation sends and empty value.

Is there a way to refresh/update @Phone variable when some text is pasted to the input control?

Here is a snipped of my code:

<input type="number" class="form-control" @bind="@Phone" @onkeypress="@(async e => await KeyWasPressed(e))" placeholder="Client Phone Number" />

@code {

    string Phone { get; set; }

    private async Task GetClientInfo()
    {
        if(String.IsNullOrWhiteSpace(Phone))
        {
            notificationMessages = $"Add a phone number";
        }
        else
        {
            showSpinner = true;

            clientInfo = await ApiHelper.GetClientInfoByPhone(Phone);           

            if(clientInfo != null)
            {
                var singleViewId = clientInfo?.SingleViewId;
                var customerNumber = clientInfo?.Accounts?.FirstOrDefault().CustomerNumber;
                var status = clientInfo?.Accounts?.FirstOrDefault().Status;
                showClientInformation = true;

                var CrossSell = clientInfo?.Accounts[0]?.CrossSell;


            }
            else
            {
                showClientInformation = false;
                notificationMessages = $"No client data for this phone ({Phone})";
            }

            showSpinner = false;
        }
    }

    private async Task KeyWasPressed(KeyboardEventArgs args)
    {
        if(args.Key == "Enter")
        {
            //await GetClientInfo();
        }
    }
}

回答1:


Direct solution:

Just use @bind-value="@Phone" @bind-value:event="oninput":


<input type="number" @bind-value="@Phone" @bind-value:event="oninput" 
       @onkeyup="@OnUserFinish"/>
<p>@clientInfo</p>

@code {
    protected string Phone { get; set; } 
    protected string clientInfo {get; set;}

    private async Task OnUserFinish(KeyboardEventArgs e)
    {
        if (e.Key == "Enter")
          clientInfo = await Fake_ApiHelper_GetClientInfoByPhone(Phone);      
    }

    private async Task<string> Fake_ApiHelper_GetClientInfoByPhone(string phone)
    {
        await Task.CompletedTask;
        return $"Client phone: {phone}";
    }
}

Bonus track:

Move to a user friendly debounce version:

@using System.Timers;

<input type="number" @bind-value="@Phone" @bind-value:event="oninput" 
       @onkeyup="@HandleKeyUp"/>
<p>@clientInfo</p>

@code {
    protected string Phone { get; set; } 
    protected string clientInfo {get; set;}
    private System.Timers.Timer aTimer;

    protected override void OnInitialized()
    {
        aTimer = new System.Timers.Timer(250);
        aTimer.Elapsed += OnUserFinish;
        aTimer.AutoReset = false;
    }

    void HandleKeyUp(KeyboardEventArgs e)
    {
        // remove previous one
        aTimer.Stop();

        // new timer
        aTimer.Start();        
    }    

    private void OnUserFinish(Object source, ElapsedEventArgs e)
    {
        InvokeAsync( async () =>
          {
            clientInfo = await Fake_ApiHelper_GetClientInfoByPhone(Phone);      
            StateHasChanged();
          });
    }

    private async Task<string> Fake_ApiHelper_GetClientInfoByPhone(string phone)
    {
        await Task.CompletedTask;
        return $"Client phone: {phone}";
    }
}



回答2:


The Reason

I could reproduce the same issue. Turns out the reason is when we copy sth & paste into the input, and then press the Enter key, the enter key event is triggered before the change event.

See the event sequence:

Because the Enter KeyPress event is triggered before the change event, the Phone property has not been updated yet.

How to fix

One possible walkaround is to listen the paste event. But unfortunately, there's currently a limitation when using Blaozr's native onpaste (See https://github.com/aspnet/AspNetCore/issues/14133#issuecomment-533198522).

Since the Team member suggests that we should use jsinterop, we can add a interHelper.handlePaste function:

<script>
    var interHelper={
        handlePaste: function (){
            var node = document.getElementById('phoneInput');
            return node.value;
        },
    }
</script>
<script src="_framework/blazor.server.js"></script>

And then refresh the latest value manually when pasting:

<input id='phoneInput' type="number" class="form-control" @bind="@Phone" 
    @onpaste="HandlePaste"
    @onkeypress="@(async e => await KeyWasPressed(e))" 
    placeholder="Client Phone Number" />

@code {
    ...

    private async Task HandlePaste(ClipboardEventArgs e){
        var str = await jsRuntime.InvokeAsync<string>("interHelper.handlePaste");
        this.Phone= str;
    }
}

Demo

Copy "107783" & Paste into the input & Press the Enter Key:



来源:https://stackoverflow.com/questions/59079326/is-there-a-way-to-update-a-binding-variable-attached-to-an-input-text-item-in-bl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!