<EditForm autocomplete="off" class="contex card-body" Model="Input" OnValidSubmit="OnSaveChangesAsync">
<!-- all fields and validations -->
<EditButton>Save changes</EditButton>
</EditForm>
我有这样的表格。它执行许多验证。然后保存更改。几乎一切正常。
问题是第一次单击该按钮不执行任何操作(似乎使该按钮处于活动状态),第二次单击实际上提交了表单。当然,它可能集中在表单元素上,但这不应阻止按钮正常工作。
如何使按钮在单击时起作用,而不是双击/第二次单击?
编辑:编辑按钮源:
EditButton.razor:
@namespace Woof.Blazor.Components
<button type="submit" class="@CssClass" @attributes="AdditionalAttributes">@ChildContent</button>
EditButton.razor.cs:
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.AspNetCore.Components;
namespace Woof.Blazor.Components {
public partial class EditButton {
[Parameter] public RenderFragment ChildContent { get; set; }
/// <summary>
/// Gets or sets a collection of additional attributes that will be applied to the created element.
/// </summary>
[Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary<string, object> AdditionalAttributes { get; set; }
string CssClass {
get {
const string defaultClass = "btn btn-primary baseline";
if (AdditionalAttributes != null &&
AdditionalAttributes.TryGetValue("class", out var @class) &&
!string.IsNullOrEmpty(Convert.ToString(@class, CultureInfo.InvariantCulture))) {
return $"{defaultClass} {@class} ";
} else return defaultClass;
}
}
}
}
让我重新说明这个问题,以使其更清楚:我怀疑按钮的第一次单击只是赋予按钮焦点(将焦点从输入元素中移出),第二次单击被注册为“提交”动作。我想跳过焦点部分,并单击鼠标第一次致电OnValidSubmit
EventCallback
。同样重要的是,当触摸按钮时,它可以在平板电脑上以这种方式工作。一键即可保存更改。意外单击按钮的后果几乎没有。如果未对表单进行任何更改,我的代码将跳过更新。如果进行了无效的更改-验证将不会触发OnValidSubmit
。进行有效更改后,但未全部输入-用户仍然可以重新编辑已保存的项目。另一方面,如果用户忘记保存更改,这将导致表单可能存在错误,而不是被更正,而用户甚至不知道发生了什么。用户可以关闭浏览器,平板设备可以锁定屏幕。几次我个人使用银行应用程序犯了类似的错误:我以为我已汇款并等待发货,却发现我尚未确认转账,而商店仍在等待我的付款。我称它为主要的烦恼,当我遇到这种情况时,我不喜欢它,所以我不希望它发生在我的应用程序用户身上。
答案 0 :(得分:2)
此答案的目的是反驳作者接受的答案的有效性 问题本身。
这是OP发布的问题代码...
@namespace Woof.Blazor.Components
<button type="submit" class="@CssClass" @attributes="AdditionalAttributes">@ChildContent</button>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Globalization;
using Microsoft.AspNetCore.Components;
namespace Woof.Blazor.Components
{
public partial class EditButton
{
[Parameter] public RenderFragment ChildContent { get; set; }
/// <summary>
/// Gets or sets a collection of additional attributes that will be applied to the created element.
/// </summary>
[Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary<string, object> AdditionalAttributes { get; set; }
string CssClass
{
get
{
const string defaultClass = "btn btn-primary baseline";
if (AdditionalAttributes != null &&
AdditionalAttributes.TryGetValue("class", out var @class) &&
!string.IsNullOrEmpty(Convert.ToString(@class, CultureInfo.InvariantCulture)))
{
return $"{defaultClass} {@class} ";
}
else return defaultClass;
}
}
}
}
以下是我出于测试目的的代码。将其复制到“索引”页面并运行该应用程序。请注意,我正在使用Blazor Server应用程序。
@page "/"
@using System
@using System.Collections.Generic
@using System.Linq
@using System.Threading.Tasks
@using System.ComponentModel.DataAnnotations
@using Woof.Blazor.Components
<EditForm Model="@Model" OnValidSubmit="@HandleValidSubmit"
OnInvalidSubmit="@HandleInvalidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="form-group">
<label for="name">Name: </label>
<InputText autocomplete="off" Id="name" Class="form-control"
@bind-Value="@Model.Name"></InputText>
<ValidationMessage For="@(() => Model.Name)" />
</div>
<div class="form-group">
<label for="body">Text: </label>
<InputTextArea autocomplete="off" Id="body" Class="form-control"
@bind-Value="@Model.Text"></InputTextArea>
<ValidationMessage For="@(() => Model.Text)" />
</div>
<EditButton>Save changes</EditButton>
</EditForm>
@code
{
private Comment Model = new Comment();
protected void HandleValidSubmit()
{
Console.WriteLine("Handle valid submit");
}
protected void HandleInvalidSubmit()
{
Console.WriteLine("Handle Invalid Submit");
}
public class Comment
{
[Required]
[MaxLength(10)]
public string Name { get; set; }
[Required]
public string Text { get; set; }
}
}
这表明您的主张
然后是问题:如果另一个编辑组件具有焦点,则该按钮必须首先获得焦点,然后才能单击
不仅是错误的,而且还清楚地揭示了您如何“选择”忽略Web和其他地方的UI元素的行为。
在“名称”字段中键入一个名称,然后用鼠标指针单击“保存更改”按钮。 DataAnnotations验证立即响应并显示以下消息:“必须输入文本字段。”
转到“输出”窗口,然后看到消息:“处理无效的提交”
返回到网页,然后在“文本字段”中输入一些文本,然后 用鼠标指针单击“保存更改”按钮。
红色短信消失。
现在转到输出窗口,看到没有消息发出,这 特别是表示click事件从未触发过。这导致你 形成错误的断言,即“点击不会被点击视为 浏览器本身。”但是,遗憾的是,从未单击“保存”。 更改”按钮。您的解释是没有意义的,对 解释这里发生了什么...
将鼠标指针指向“保存更改”按钮,然后 尝试单击它,“文本”字段失去焦点,其结果是 是DataAnnotations代码删除红色消息,并随后重新呈现 涉及的组件。这样做的速度使您无法 产生将在重新渲染之前执行的点击。该代码是 以光速执行,但即使您足够快( 右),以在将焦点松开到 启动重新渲染,代码以给定的顺序执行。在任何 在这种情况下,事实仍然是重新渲染组件,而您没有 成功触发或发出点击事件,因为“保存更改” 按钮没有焦点。正如我在测试1中所展示的,不需要重点。它 从一开始就一直是这样:)
如您所见,红色消息已被删除,也就是说,重新呈现 组件已发生。 4.现在,当焦点位于“名称”字段中时,用鼠标指针单击 “保存更改”按钮。 5.转到“输出”窗口,然后看到消息:“处理有效的提交”
添加以下onmouseover =“ document.getElementById('name')。focus();”到按钮 EditButton.razor文件中的元素。这是代替onmouseover =“ this.focus()” 在接受的答案中用作解决方案。
在“名称”字段中键入一个名称,然后用鼠标指针单击“保存更改”按钮。 DataAnnotations验证立即响应并显示以下消息:“必须输入文本字段。”
转到“输出”窗口,然后看到消息:“处理无效的提交”
返回到网页,然后在“文本字段”中输入一些文本。现在, 沿“保存更改”按钮的方向移动鼠标时, 将触发mouseover事件,并将焦点设置在“名称”字段。
现在,当焦点位于“名称”字段中时,用鼠标指针单击 “保存更改”按钮。
转到“输出”窗口,然后看到以下消息:“处理有效的提交”
请注意,通过将onmouseover =“ this.focus()”与 onmouseover =“ document.getElementById('name')。focus();”一样 显然,您不必将“保存更改”按钮的焦点设置在 发出一次点击。只有在 与代码相关的DataAnnotations刷新了组件。
总结:无论您在回答中说了什么,以及评论都是毫无根据的, 错误和误导。我同意的唯一断言是,这是一个简单的问题: “您至少犯了2个错误。首先:您误认为了一个简单的问题”
是的,这是一个简单的问题,鉴于您提供的详细信息,我已经提供了答案, 是正确的,甚至不能被当前答案无效。
请删除您的答案,因为它具有误导性和错误性。当然不应该接受。
答案 1 :(得分:0)
问题是第一次单击按钮不会执行任何操作
您期望它做什么?您是否有希望执行的代码,但没有。
提交表格
该表格永远不会提交。这是SPA应用程序,您不能提交,或者更确切地说,您不应该提交表单数据。您向哪里提交数据表格。请将以下代码放入OnSaveChangesAsync方法中,仅单击一次按钮,然后在“输出”窗口中查看结果:
private void OnSaveChangesAsync()
{
Console.WriteLine(Input.<Type a property name defined in the Input
object>);
}
如果给定属性的值打印在“输出”窗口中,则一切正确。如果没有,请发布所有代码以及对自定义EditButton的引用。