问题
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