问题
I have a simple application with an input field that should insert a predefined piece of text as you type.
The code I have looks like this:
<input type="text" bind="@PetitionInput" onkeydown="@PetitionHandleKeyDown" />
@functions
{
private int _petitionCharStep = 0;
private string _petition = "This is a dummy text";
public string PetitionInput { get; set; } = string.Empty;
void PetitionHandleKeyDown(UIKeyboardEventArgs arg) {
PetitionInput += _petition[_petitionCharStep];
_petitionCharStep++;
Console.WriteLine(PetitionInput);
}
}
When the input field has focus, and I press a letter on my keyboard, then it should add the first letter from the string _petition
to the input. When I press any letter on my keyboard, it should enter the second letter into the input field. And so on.
The problem I have is that it also adds the letter at the end of the input that I pressed on my keyboard. I want to prevent that from happening.
Is there a way to fix this using issue Blazor
code only?
I have an online demo here.
回答1:
You can think a little differently in Blazor.
Rather than using "bind" and preventing the keystroke, you can set the "value" and handle the "oninput" event, like this:
https://blazorfiddle.com/s/azdn892n
@page "/"
<h1>Start typing something...</h1>
<input type="text" value="@PetitionInput" oninput="@PetitionHandleKeyDown" />
@functions {
private int _petitionCharStep = 0;
private string _petition = "This is a dummy text";
public string PetitionInput { get; set; } = string.Empty;
void PetitionHandleKeyDown(UIChangeEventArgs arg) {
PetitionInput = _petition.Substring(0,++_petitionCharStep);
Console.WriteLine(PetitionInput);
}
}
I can't imagine why you would want to do this, and there are many extra things you need to do to cover backspaces, arrow keys, tab etc...
回答2:
Ok, this is a bit dirty tricky: remove the last char to override user input key:
<input type="text"
value="@PetitionInput"
onkeydown="@PetitionHandleKeyDown"
onkeyup="@PetitionHandleKeyUp"
/>
// ...
private int _petitionCharStep = 0;
private string _petition = "This is a dummy text";
public string PetitionInput { get; set; } = string.Empty;
void PetitionHandleKeyDown(UIKeyboardEventArgs arg) {
if (_petitionCharStep >= _petition.Length )
{
PetitionInput = _petition.Substring(0, _petition.Length-1 );
_petitionCharStep--;
}
}
void PetitionHandleKeyUp(UIKeyboardEventArgs arg) {
if (_petitionCharStep < _petition.Length )
{
PetitionInput += _petition[_petitionCharStep];
_petitionCharStep++;
}
}
Test it at blazorfiddle.
回答3:
The following is intended for the bewildered, explaining how data binding works in Blazor:
Using bind with the PetitionInput property (<input bind="@PetitionInput" />
) is essentially equivalent to the following:
<input value="@PetitionInput"
onchange="@((UIChangeEventArgs __e) => PetitionInput= __e.Value)" />
"When the component is rendered, the value of the input element comes from the PetitionInput property. When the user types in the text box, the onchange event is fired and the PetitionInput property is set to the changed value. In principle, bind associates the current value of an expression with a value attribute and handles changes using the registered handler."
In plain words, when you use the bind attribute (bind="@PetitionInput"), Blazor generate code similar to this:
<input value="@PetitionInput"
onchange="@((UIChangeEventArgs __e) => PetitionInput= __e.Value)" />
This is the so-called two-way data binding. Now, if you add an event handler for the onkeydown event, the code does what it is designed to do:
void PetitionHandleKeyDown(UIKeyboardEventArgs arg) {
PetitionInput += _petition[_petitionCharStep];
_petitionCharStep++;
}
When the page is displayed for the first time, the text box is empty as the default value of PetitionInput is set to string.Empty:
public string PetitionInput { get; set; } = string.Empty;
When the user type in the text box, say, the letter 'N', it is added to the PetitionInput property due to the two-way binding (using bind attribute), and displayed in the text box, immediately after the hosting Component has been rendered. Additionally, the code in the PetitionHandleKeyDown method add the letter 'T' to the PetitionInput property (first time you type), and thus the string "NT" is displayed in the text box, immediately after the hosting Component has been rendered. Of course the way to prevent such behaviour (we must respect the wish of the questioner) is to do what
Mister Magoo did above. Simple and elegant, and reflect understanding of data-binding and how Blazor works.
Hope this helps... At least, I know, it helped me.
来源:https://stackoverflow.com/questions/55328157/preventdefault-on-blazor-input