Search code examples
asp.net-corekeypressblazorblazor-server-side

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


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();
        }
    }
}

Solution

  • 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}";
        }
    }