【问题标题】:Submit Form when it loses focus失去焦点时提交表单
【发布时间】:2019-07-23 11:37:22
【问题描述】:

我必须构建一个包含大量字段(可能 >1000 个字段)的表单。由于recommended GET URL length limit,我想将其拆分为几个较小的表单(每个表单有 12 个字段),在完成后提交。

基本上我正在寻找的是某种 form.onBlur 事件:我只想在以下情况下提交表单:

  • 其中一个输入失去焦点(模糊)
  • 此表单的其他输入都没有焦点

关于处理这个问题的好方法有什么想法吗?也许我需要让每个 input.onBlur 事件检查表单其他输入的当前焦点状态?

编辑:我非常了解 GET 与 POST,包括安全问题和数据量。对于我的特定设置的特定问题,GET 请求是唯一的选择;所以这个问题。

【问题讨论】:

  • 如果您的表单真的那么大,您可能不应该使用GET,而是使用POST。对于如此大的负载,您没有理由使用 GET 提交。
  • 很遗憾,POST 在这种情况下不是一个选项(仅限前端开发)
  • “遗憾的是,在这种情况下,POST 不是一个选项(仅限前端开发)”......这没有任何意义。如果您不负责后端,那很好,但是您必须与负责的人交谈,并说他们将其设计为仅接受 GET 请求的方式是不切实际的。它甚至可能导致安全漏洞(例如,如果包含个人详细信息或类似信息的表单数据位于 URL 的查询字符串中,它可能最终出现在服务器日志等中,它可能会持续数年和/或对不需要查看它的人可见. 通过 GET 提交详细数据通常不是一个好主意。)
  • 最重要的是,正如我所概述的,如果不对后端进行某种更改,您将无法解决此问题。因此,如果需要进行更改,最简单和最明显的解决方案是转而使用 POST。您可以将其拆分为许多较小的 GET,但这需要更多的工作,并且无论如何都需要在前端和后端进行更改。究竟为什么你声称不可能使用 POST?如果只是你不能请求对后端进行更改,那么由于我刚才提到的原因(即拆分它仍然需要后端更改),它不会被洗掉。
  • 后端是一个带有扩展名的CMS。该扩展内置了对 GET 变量的支持,但不支持 POST。对了,对你来说够清楚了吗?

标签: javascript html


【解决方案1】:

根据我的评论,如果您的表单那么大,您真的不应该使用GET。另外,GET 请求仅在您想清楚地保留浏览器历史记录中的状态时才有用。在您的情况下,实际上使用 POST 更有意义。

抛开技术性问题不谈,您可能想看看从表单中的任何输入元素中听到focusout event 冒泡。附加blur 事件感觉很直观,但由于它不会冒泡,因此您必须将其附加到每个输入元素,这很昂贵。

formElement.addEventListener('focusout', e => {
  formElement.submit();
});

document.getElementById('my-form').addEventListener('focusout', e => {
  console.log('focus lost');
});
input, textarea, select {
  display: block;
}
<form id="my-form">
  <input type="text" />
  
  <input type="checkbox" />
  
  <input type="radio" name="group1" value="1" />
  <input type="radio" name="group1" value="2" />
  <input type="radio" name="group1" value="3" />
  
  <select>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
</form>

【讨论】:

  • 这实际上并没有回答我的问题。我只想在所有输入都失去焦点后提交表单。每次输入失去焦点时都会触发(例如,如果我选择 1,然后选择 2,它已经被触发)
  • @E.Villiger 所有输入都失去焦点是什么意思?当您首先加载页面时,无论如何都不会关注任何输入。也许您想要的是验证表单。
  • 我认为唯一的歧义是“形式”在某些方面的含义。 OP 指定了更小的表单,每页有几个。
  • @D_N 不仅如此。我认为在 OP 明确他真正想要什么样的用户体验行为之前,继续前进是毫无意义的。由于无法同时聚焦所有表单元素,因此您无法知道所有输入何时失去焦点。跟踪单个焦点事件是可能的,但这增加了什么价值?并非每个 focusout 事件都表明输入值发生了变化。
  • 我不打算讨论你的解决方案,但我认为需要的不仅仅是 OP 和严格的情况,而是从回答问题到重新设计他们的整个设置。
【解决方案2】:

鉴于每个 form_element 都可以通过一个类来识别,你可以用它来做一些有风格的事情

$(".form_element").on("focusout", function(){
  let do_query = true;
  setTimeout(function(){
     $(".form_element:input").each(function(){ 
       if($(this).is(":focus")){
         do_query = false;
         return false; //Exit the each loop
       }
     });

     if(do_query){
        console.log("I'm going to perform the query");
     }

  }, 200);
});

我发现如果没有设置超时,它总是会触发 false,因为新元素没有时间获得它的焦点。

在此处查看jsfiddle 的工作示例

【讨论】:

  • 对于检测焦点的非 jQuery 方法:stackoverflow.com/a/17614883/241244。 (你的意思是$(this).find(':input')$someVarStoringThisForm.find(':input') 限制为单个表单吗?)
  • 如果你在这里说 $(this).find(':input') 它只会针对刚刚失去焦点的 jQuery 元素。因此提到了 $(".form_element:input") 。在给定元素失去焦点后,他想检查 all 其他 form_element 是否失焦。
  • 请注意,您可以使用 Stack Snippets 在 Stack Overflow 上提供一个可运行的示例,这样人们就不必转到其他站点。
  • 我误读了您的解决方案。我以为您是在选择表单然后获取所有输入。看来,Focusout 气泡,所以你可以这样做。
  • 谢谢,这正是我想要的!我希望可能有一种更直接、更简单的方法,但我可能只需要这样做!
猜你喜欢
  • 2010-10-08
  • 1970-01-01
  • 2013-08-29
  • 2012-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-05
  • 1970-01-01
相关资源
最近更新 更多