我找到了这篇文章,但我很难理解如何防止任何<input>
独立地提交"enter"键
<EditForm Model="exampleModel" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" @bind-Value="exampleModel.Name" />
<InputText id="name2" @bind-Value="exampleModel.Name2" />
<button type="submit">Submit</button>
</EditForm>
@code {
private ExampleModel exampleModel = new ExampleModel();
private void HandleValidSubmit()
{
Console.WriteLine("OnValidSubmit");
}
public class ExampleModel
{
[Required]
[StringLength(10, ErrorMessage = "Name is too long.")]
public string Name { get; set; }
public string Name2 {get; set;}
}
}
用例
输入键 在HTML表单上,如果您正在填写文本框并按回车键,即使您尚未完成其余信息的填写,它也将提交表单。有许多网站使用此功能,例如当您按回车键时,Google搜索框将提交。这有效,因为您只有一个文本框要填写,但如果有多个字段要填写,您不希望在 Enter 键上提交表单。
Leonardo Lurci,这是一个纯粹用C#实现的完整解决方案,没有JSInterop。事实证明,Microsoft已经提供了此功能,但他们没有提供足够的示例来演示如何使用它。
事实证明,我不能将@onkeypress="@KeyHandler"
和@onkeypress:preventDefault
对与 InputText 等表单组件一起使用,但将这些指令应用于 Html 标签是可行的,并且运行良好。例如,请参阅如何将这些指令应用于"提交"按钮。
因此,我对基类 InputBase 进行子类化,这是 InputText 组件派生的类,通过添加一个输入元素来覆盖默认视图呈现,我可以在其中添加新功能的指令。
TextBox.razor(代替InputText)
@inherits InputBase<string>
<input type="text" value="@CurrentValueAsString" id="Id" class="@CssClass"
@onkeydown="KeyDownHandler" @onkeypress="KeyPressHandler"
@onkeypress:preventDefault/>
@code{
protected override bool TryParseValueFromString(string value, out string
result, out string validationErrorMessage)
{
result = value;
validationErrorMessage = null;
return true;
}
void KeyDownHandler(KeyboardEventArgs args)
{
if (args.Key == "Backspace" && CurrentValueAsString.Length >=1)
{
CurrentValueAsString = CurrentValueAsString.Substring(0,
CurrentValueAsString.Length - 1);
}
}
void KeyPressHandler(KeyboardEventArgs args)
{
if (args.Key == "Enter")
{
return;
}
var key = (string)args.Key;
CurrentValueAsString += key;
}
}
用法
<p>Leave me a comment</p>
<EditForm Model="Model" OnValidSubmit="HandleValidSubmit" >
<DataAnnotationsValidator />
<div class="form-group">
<label for="name">Name: </label>
<TextBox Id="name" Class="form-control" @bind-Value="@Model.Name" >
</TextBox>
<ValidationMessage For="@(() => Model.Name)" />
</div>
<div class="form-group">
<label for="body">Text: </label>
<InputTextArea Id="body" Class="form-control" @bind-Value="@Model.Text" >
</InputTextArea>
<ValidationMessage For="@(() => Model.Text)" />
</div>
<p>
<button type="submit" @onkeypress="KeyHandler" @onkeypress:preventDefault>
Submit
</button>
</p>
</EditForm>
@code
{
private Comment Model = new Comment();
private void HandleValidSubmit()
{
Console.WriteLine("Submit...");
}
void KeyHandler(KeyboardEventArgs args)
{
if (args.Key == "Enter")
{
return;
}
}
public class Comment
{
public string Name { get; set; } = "Jeff";
public string Text { get; set; } = "I'm Jeff. I'm from Canada";
}
}
请不要犹豫,提出任何问题
希望这有帮助...
将事件处理程序添加到输入并提交如下所示的元素:
<InputText id="name" @bind-Value="exampleModel.Name" @onkeydown="PreventSubmit"/>
<button type="submit" @onclick="ShouldISubmit">Submit</button>
将此添加到您的@code块:
public bool shouldsubmit { get; set; }
public bool entersubmit { get; set; }
public void PreventSubmit(KeyboardEventArgs ev)
{
if (ev.Key == "Enter")
entersubmit = true;
}
public void ShouldISubmit()
{
if (entersubmit)
shouldsubmit = false;
else
shouldsubmit = true;
entersubmit = false;
}
将您的提交功能更改为此
private void HandleValidSubmit()
{
if (shouldsubmit) {
Console.WriteLine("OnValidSubmit");
}
}
正如Enet在评论中建议的那样,对于这个用例,没有完整的Blazor(Csharp)解决方案。你必须与 JavaScript 交互。
目前,我用这个解决方法解决了:
布莱泽侧
@inject IJSRuntime JS
<EditForm id="askQuestionForm" Model="exampleModel" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" @bind-Value="exampleModel.Name" />
<InputText id="name2" @bind-Value="exampleModel.Name2" />
<button type="submit">Submit</button>
</EditForm>
@code {
private ExampleModel exampleModel = new ExampleModel();
private void HandleValidSubmit()
{
Console.WriteLine("OnValidSubmit");
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
JS.InvokeVoidAsync("PreventEnterKey", "askQuestionForm");
}
}
public class ExampleModel
{
[Required]
[StringLength(10, ErrorMessage = "Name is too long.")]
public string Name { get; set; }
public string Name2 {get; set;}
}
}
互操作.js
function PreventEnterKey(id) {
$(`#${id}`).keydown(function (event) {
if (event.keyCode == 13) {
event.preventDefault();
return false;
}
});
}
我希望Microsoft将来会开发此功能。
感谢Enet。
我找到了一个简单的解决方案,我认为这是最简单的选择。 创建一个自定义组件,该组件将成为您的提交按钮:
<button type="button" @onclick="OnClick" @attributes="UnmatchedAttributes">@Text</button>
@code {
[Parameter]
public string Text { get; set; }
[Parameter]
public Func<Task> OnValidSubmitAsync { get; set; }
[Parameter]
public Action OnValidSubmit { get; set; }
[CascadingParameter]
public EditContext EditContext { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> UnmatchedAttributes { get; set; }
private async Task OnClick() {
if (EditContext != null) {
if (EditContext.Validate()) {
if (OnValidSubmit != null) {
OnValidSubmit();
} else {
if (OnValidSubmitAsync != null) {
await OnValidSubmitAsync();
}
}
}
}
}
}
此组件充当提交按钮,但由于其类型不是提交,因此 Enter 不会触发它。它接受 EditContext 类型的级联参数,该参数允许它验证表单。它还接受一个委托,该委托将在单击时触发,并且表单状态有效。
使用示例:
<EditForm Model="model">
<input type="text" @bind="model.Value" />
@* Add the custom submit component*@
<EditFormSubmit Text="Submit" OnValidSubmit="Submit" class="btn btn-primary"></EditFormSubmit>
</EditForm>
这是我的解决方案。相当精益的代码,没有js。这样,您就不会直接阻止 Enter 键的默认行为。相反,您可以控制表单是否应根据 Enter 键事件继续提交。
在编辑表单声明中
<EditForm OnValidSubmit="@Submit" @onkeydown="HandleKeyDown">
在您的代码中:
private bool allowFormSubmit = true;
protected void HandleKeyDown(KeyboardEventArgs args)
{
allowFormSubmit = !(args.Key == "Enter");
}
protected async Task Submit()
{
//consume the Enter key and reset to allow form submission on submit click
if (!allowFormSubmit)
{
allowFormSubmit = true;
return;
}
//Your submit code
}
首先,您应该了解浏览器在这种情况下的行为方式。 如果表单中有<button type="submit">
,并且用户按 Enter 键,浏览器将在按钮上模拟click
事件。
与其取消按键事件,不如使用带有capture: true
addEventListener
来阻止单击事件。
只需添加以下javascript:
//prevent submit on enter
document.body.addEventListener('keypress', e => {
if (e.which == ENTER && !e.target.matches('button[type=submit]')) {
/** @type {HTMLFormElement} */
const form = e.composedPath().find(e => e.matches('form'))
/** @type {HTMLButtonElement} */
const submitButton = form && form.querySelector('button[type=submit]:enabled');
if (submitButton) {
const preventSubmit = (e2) => {
e2.preventDefault();
return false;
}
// Browser emulates submit button click, when enter key is pressed, so we need to prevent that.
form.addEventListener('click', preventSubmit, { once: true, capture: true });
setTimeout(() => form.removeEventListener('click', preventSubmit, { capture: true }), 0); // better clear the eventlistener despite once:true in case the keypress propagation has been stopped by some other eventhandler
}
}
});
它适用于 Blazor Server 和 Blazor WebAssembly,无需接触现有代码。
演示:https://blazorrepl.com/repl/mvYgPhPx007ySOGe03
因此,正如其他答案中所讨论的,如果按下 Enter 键时有一个可用的提交按钮,浏览器将自动"单击"一个提交按钮,除非您使用 JS 来阻止它,或者将事件处理程序添加到每个文本框以防止它。
我扩展了Michael的答案,并创建了一个更灵活的"提交"按钮来绕过标准的提交行为。注意:这将使您的表单对可访问性不太友好。请考虑此解决方案是否适合您的项目。
SubmitButton.razor
<button type="button" @onclick="OnClick" @attributes="UnmatchedAttributes">@ChildContent</button>
@code {
[Parameter]
public RenderFragment? ChildContent { get; set; }
[Parameter]
public EventCallback OnValidSubmit { get; set; }
[CascadingParameter]
public EditContext? EditContext { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object>? UnmatchedAttributes { get; set; }
private async Task OnClick()
{
if (EditContext != null && EditContext.Validate())
{
await OnValidSubmit.InvokeAsync();
}
}
}
用法(例如 Bootstrap 类和 FontAwesome 图标)
<EditForm Model="@model">
@* Add your form elements *@
<SubmitButton class="btn btn-success" OnValidSubmit="HandleValidSubmit"><i class="fas fa-save me-2"></i>Submit</SubmitButton>
</EditForm>
@code {
private async Task HandleValidSubmit()
{
// Do your thing!
}
}
编辑:看来您需要在页面上使用另一个@onkeypress
。
我不得不承认以下内容比原始解决方案要复杂一些......但它对😅误导性信息感到抱歉。
<EditForm Model="exampleModel" OnValidSubmit="HandleValidSubmit" @onkeypress:preventDefault="preventDefault">
<InputText @bind-Value="exampleModel.Name1" @onkeypress="@(e => preventDefault = e.Key == "Enter")" />
<button type="submit">submit</button>
</EditForm>
@code {
public bool preventDefault { get; set; } = false;
}
<小时 /><小时 />有点晚了,但想通了
@onkeydown:preventDefault="true"
在您的编辑表单组件中也可以解决问题。
<EditForm Model="exampleModel" @onkeydown:preventDefault="true" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" @bind-Value="exampleModel.Name" />
<InputText id="name2" @bind-Value="exampleModel.Name2" />
<button type="submit">Submit</button>
</EditForm>
保持简单方法:
-
将项添加到项的类定义中,对于 WhatToDo:
public string WhatToDo { get; set; }
-
添加一个不可见的按钮作为提交按钮中的第一个按钮,以及
-
在 OnSubmit 方法中测试其值。 如果用户只按 Enter 键,将返回此按钮的值。
如果它的值是(在我的例子中是"无所事事"),那么只需返回。
<EditForm..... with OnSubmit parameters>
...
<button type="submit" @onclick="@(()=> selectedItem.WhatToDo = "DoNothing")" class="btn btn-primary" style="display:none;">Do Nothing</button>
<button type="submit" @onclick="@(()=> selectedItem.WhatToDo = "Save")" class="btn btn-primary">Save</button>
<button type="submit" @onclick="@(()=> selectedItem.WhatToDo = "ExitWOSave")" class="btn btn-primary">Exit w/o Saving</button>
</EditForm>
@code {
private async Task InsertOrUpdateItem()
{
Console.WriteLine("WhatToDo is XX" + selectedItem.WhatToDo + "XX");
if (selectedItem.WhatToDo == "ExitWOSave") //test for this first
{
// Navigate away…
return;
};
if (selectedItem.WhatToDo == "DoNothing")
{ return; }
if (selectedItem.WhatToDo == "Save")
{ //do your save…
return;
}
}