Blazor:如何通过单击按钮提交表单

时间:2020-04-20 12:12:42

标签: blazor blazor-server-side

<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。进行有效更改后,但未全部输入-用户仍然可以重新编辑已保存的项目。另一方面,如果用户忘记保存更改,这将导致表单可能存在错误,而不是被更正,而用户甚至不知道发生了什么。用户可以关闭浏览器,平板设备可以锁定屏幕。几次我个人使用银行应用程序犯了类似的错误:我以为我已汇款并等待发货,却发现我尚未确认转账,而商店仍在等待我的付款。我称它为主要的烦恼,当我遇到这种情况时,我不喜欢它,所以我不希望它发生在我的应用程序用户身上。

2 个答案:

答案 0 :(得分:2)

此答案的目的是反驳作者接受的答案的有效性 问题本身。

这是OP发布的问题代码...

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.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; }

        }
    }

测试1

  1. 在“名称”字段中键入一个名称,然后跳至“文本”字段。
  2. 输入一些文本,但不要按Tab键:将输入焦点保留在“文本”字段中。
  3. 使用鼠标指针单击“保存更改”按钮,然后转到“输出”窗口
  4. 如您所见,单击按钮已提交表单,并打印了文本:“处理有效的提交”

这表明您的主张

然后是问题:如果另一个编辑组件具有焦点,则该按钮必须首先获得焦点,然后才能单击

不仅是错误的,而且还清楚地揭示了您如何“选择”忽略Web和其他地方的UI元素的行为。

测试2

  1. 在“名称”字段中键入一个名称,然后用鼠标指针单击“保存更改”按钮。 DataAnnotations验证立即响应并显示以下消息:“必须输入文本字段。”

  2. 转到“输出”窗口,然后看到消息:“处理无效的提交”

  3. 返回到网页,然后在“文本字段”中输入一些文本,然后 用鼠标指针单击“保存更改”按钮。

  4. 红色短信消失。

  5. 现在转到输出窗口,看到没有消息发出,这 特别是表示click事件从未触发过。这导致你 形成错误的断言,即“点击不会被点击视为 浏览器本身。”但是,遗憾的是,从未单击“保存”。 更改”按钮。您的解释是没有意义的,对 解释这里发生了什么...

    将鼠标指针指向“保存更改”按钮,然后 尝试单击它,“文本”字段失去焦点,其结果是 是DataAnnotations代码删除红色消息,并随后重新呈现 涉及的组件。这样做的速度使您无法 产生将在重新渲染之前执行的点击。该代码是 以光速执行,但即使您足够快( 右),以在将焦点松开到 启动重新渲染,代码以给定的顺序执行。在任何 在这种情况下,事实仍然是重新渲染组件,而您没有 成功触发或发出点击事件,因为“保存更改” 按钮没有焦点。正如我在测试1中所展示的,不需要重点。它 从一开始就一直是这样:)

测试3

  1. 在“名称”字段中键入一个名称,然后用鼠标指针单击“保存更改”按钮。 DataAnnotations验证立即响应并显示以下消息:“必须输入文本字段。”
  2. 转到“输出”窗口,然后看到以下消息:“处理无效的提交”
  3. 返回到网页,然后在“文本字段”中输入一些文本,然后 用鼠标指针将焦点移到“名称”字段。

如您所见,红色消息已被删除,也就是说,重新呈现 组件已发生。 4.现在,当焦点位于“名称”字段中时,用鼠标指针单击 “保存更改”按钮。 5.转到“输出”窗口,然后看到消息:“处理有效的提交”

测试4

  1. 添加以下onmouseover =“ document.getElementById('name')。focus();”到按钮 EditButton.razor文件中的元素。这是代替onmouseover =“ this.focus()” 在接受的答案中用作解决方案。

  2. 在“名称”字段中键入一个名称,然后用鼠标指针单击“保存更改”按钮。 DataAnnotations验证立即响应并显示以下消息:“必须输入文本字段。”

  3. 转到“输出”窗口,然后看到消息:“处理无效的提交”

  4. 返回到网页,然后在“文本字段”中输入一些文本。现在, 沿“保存更改”按钮的方向移动鼠标时, 将触发mouseover事件,并将焦点设置在“名称”字段。

  5. 现在,当焦点位于“名称”字段中时,用鼠标指针单击 “保存更改”按钮。

  6. 转到“输出”窗口,然后看到以下消息:“处理有效的提交”

  7. 请注意,通过将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的引用。

相关问题