【问题标题】:EditForm - How can I prevent submit on pressing enter keyEditForm - 如何防止按回车键提交
【发布时间】:2020-09-15 04:13:55
【问题描述】:

我找到了this article,但我很难理解如何防止任何<input> 独立地在“输入”键上提交

<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 表单上,如果您正在填写文本框并按下回车键,即使您尚未完成其余信息的填写,它也会提交表单。有许多网站使用此功能,例如当您按 Enter 键时会提交 Google 搜索框。之所以可行,是因为您只有一个文本框要填写,但如果要填写多个字段,您不希望表单按 Enter 键提交。

【问题讨论】:

  • 在写我的之前我已经看过这个问题了。我决定写一个新的,因为在表单中放置了两个提交按钮,这似乎不是一个好的解决方案,而只是出于某种原因的一种解决方法。无论如何,@enet 我已经尝试过您的解决方案,但是如果我多次按“输入”,则在一种情况下表单仍会运行提交
  • 在一个表单中有两个提交按钮是荒谬的小丑,而不是编程。它绝对不属于解决方法的含义。我再次运行我的代码,它永远不允许提交,只要提交按钮具有输入焦点并且您按 Enter 键。如果另一个控件(例如文本框)具有输入焦点,并且您按下 Enter 键,那么如果您的数据有效,那么当然会执行提交操作。
  • 我同意你的看法。这就是为什么我提出一个新问题。问题标题“编辑表单-...”背后有一个含义,因为我想阻止它来自编辑表单中包含的任何输入。
  • 我理解你...如果可以的话,我会寻找解决方案。要求重新打开您的问题。没有理由关闭它。
  • Leonardo Lurci,很抱歉,但我认为目前无法在 Blazor 中完成此操作,除非您使用 JSInterop。我在 github 上寻求帮助,但无济于事。 Blazor 团队成员将有类似问题的用户重定向到 stackoverflow。这个特性非常重要,我希望 Blazor 团队可以提供一个解决方案......

标签: blazor


【解决方案1】:

正如 Enet 在 cmets 中所建议的那样,没有针对此用例的完整 Blazor (Csharp) 解决方案。您必须与 JavaScript 交互。

目前,我用这个解决方法解决了:

blazor 方面

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

interop.js

function PreventEnterKey(id) {
    $(`#${id}`).keydown(function (event) {
        if (event.keyCode == 13) {
            event.preventDefault();
            return false;
        }
    });
}

我希望微软将来会开发这个功能。

感谢 Enet。

【讨论】:

    【解决方案2】:

    Leonardo Lurci,这是一个完全用 C# 实现的完整解决方案,没有 JSInterop。事实证明,微软已经提供了这个功能,但他们没有提供足够的示例来演示如何使用它。

    事实证明,我不能将 @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";
            }
    
        }
    

    请不要犹豫,问任何问题

    希望这会有所帮助...

    【讨论】:

    • 如果焦点元素是第 3 方控件怎么办?
    【解决方案3】:

    保持简单的方法:

    1. 在你的 Item 的类定义中添加一个项目,用于 WhatToDo:

      public string WhatToDo { get; set; }
      
    2. 添加一个不可见按钮作为提交按钮中的第一个按钮,并且

    3. 在您的 OnSubmit 方法中测试其值。如果用户只是按回车,就会返回这个按钮的值。

    如果它的值是(在我的例子中是“DoNothing”)然后简单地返回。

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

    【讨论】:

      【解决方案4】:

      将事件处理程序添加到您的输入并提交如下元素:

      <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");
          }
      }
      

      【讨论】:

        【解决方案5】:

        首先,您应该了解浏览器在这种情况下的行为方式。 如果表单中有&lt;button type="submit"&gt;,并且用户按下回车,浏览器将模拟按钮上的click事件。

        您可以使用addEventListenercapture: true 来阻止点击事件,而不是取消按键事件。

        只需添加以下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

        【讨论】:

          【解决方案6】:

          我找到了一个简单的解决方案,我认为这是最简单的选择。 创建一个自定义组件作为您的提交按钮:

          <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();
                              }
                          }
                      }
                  }
              }
          
          }
          

          这个组件作为一个提交按钮,但是由于它的类型不是提交,一个回车不会触发它。它接受 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>
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-11-18
            • 2014-07-10
            • 1970-01-01
            相关资源
            最近更新 更多