使用 Ctrl +V 组合键时,是否可以更新附加到 Blazor 中输入文本项的绑定变量?
Is there a way to update a binding variable attached to an Input text Item in Blazor when using Ctrl +V combination keys?
我有这个输入,用于捕获 phone 号码。
当用户输入一个数字并按下 "Enter" 键时,触发方法 "KeyWasPressed" 并进行一些验证。这按预期工作但是...
例如,当用户从 excel 复制并粘贴数字时,变量 @Phone
不会更新其值,因此当用户按下 "Enter" 验证发送的键和空值。
有没有办法在将一些文本粘贴到输入控件时 refresh/update @Phone
变量?
这是我的代码片段:
<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();
}
}
}
原因
我可以重现同样的问题。原来是因为当我们copy sth & paste到input里,然后按下Enter
键,enter
键事件在之前被触发change
事件。
查看事件顺序:
因为Enter KeyPress事件在change事件之前触发,所以Phone
属性还没有更新
如何修复
一种可能的解决方法是监听粘贴事件。但不幸的是,目前在使用 Blaozr 的原生 onpaste 时存在限制(参见 https://github.com/aspnet/AspNetCore/issues/14133#issuecomment-533198522)。
既然团队成员建议我们应该使用jsinterop
,我们可以添加一个interHelper.handlePaste
功能:
<script>
var interHelper={
handlePaste: function (){
var node = document.getElementById('phoneInput');
return node.value;
},
}
</script>
<script src="_framework/blazor.server.js"></script>
然后粘贴时手动刷新最新值:
<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;
}
}
演示
复制“107783”并粘贴到输入中并按 Enter
键:
直接解:
只需使用@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}";
}
}
奖励曲目:
移动到用户友好的去抖动版本:
@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}";
}
}
我有这个输入,用于捕获 phone 号码。 当用户输入一个数字并按下 "Enter" 键时,触发方法 "KeyWasPressed" 并进行一些验证。这按预期工作但是...
例如,当用户从 excel 复制并粘贴数字时,变量 @Phone
不会更新其值,因此当用户按下 "Enter" 验证发送的键和空值。
有没有办法在将一些文本粘贴到输入控件时 refresh/update @Phone
变量?
这是我的代码片段:
<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();
}
}
}
原因
我可以重现同样的问题。原来是因为当我们copy sth & paste到input里,然后按下Enter
键,enter
键事件在之前被触发change
事件。
查看事件顺序:
因为Enter KeyPress事件在change事件之前触发,所以Phone
属性还没有更新
如何修复
一种可能的解决方法是监听粘贴事件。但不幸的是,目前在使用 Blaozr 的原生 onpaste 时存在限制(参见 https://github.com/aspnet/AspNetCore/issues/14133#issuecomment-533198522)。
既然团队成员建议我们应该使用jsinterop
,我们可以添加一个interHelper.handlePaste
功能:
<script>
var interHelper={
handlePaste: function (){
var node = document.getElementById('phoneInput');
return node.value;
},
}
</script>
<script src="_framework/blazor.server.js"></script>
然后粘贴时手动刷新最新值:
<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;
}
}
演示
复制“107783”并粘贴到输入中并按 Enter
键:
直接解:
只需使用@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}";
}
}
奖励曲目:
移动到用户友好的去抖动版本:
@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}";
}
}