首页 > 解决方案 > 使用javascript拦截表单提交事件

问题描述

我正在使用带有 Bootstrap-4 的 Rails-6。我正在使用 Bootstrap Card 来显示我的表单。表单很简单,带有标签、文本字段、文件上传和提交按钮。 这是输出 这是我的表单的代码:

<%= javascript_pack_tag 'photo', 'data-turbolinks-track': 'reload' %>
<div class="card text-center">
  <div class="card-header">
    Add New Photo
  </div>
  <div class="card-body">
    <%= form_for @photo do |f| %>
      <%= render "shared/errors", object: @photo %>
      <%= f.hidden_field :image, value: @photo.cached_image_data %>
      <%= f.label :title %>
      <%= f.text_field :title %>
      <%= f.label :image %>
      <%= f.file_field :image %>
      <% if @photo.image_data? %>
        <%= image_tag @photo.image_url(:medium) %>
        Remove attachment: <%= f.check_box :remove_image %>
      <% end %>
      <%= f.submit %>
    <% end %>
  </div>
  <div class="card-footer text-muted">
  </div>
</div>

在我的 Javascript 包中,我使用 javascript 拦截了表单提交事件。

$(document).ready(function(){
  function processForm(e) {
      if (e.preventDefault) e.preventDefault();
      alert('intercepted form submission');
      /* do what you want with the form */
      // You must return false to prevent the default form behavior
      return false;
  }

  var form = document.getElementById('new_photo');
  if (form.attachEvent) {
      form.attachEvent("submit", processForm);
      alert('attachEvent');
  } else {
      form.addEventListener("submit", processForm);
      alert("addEventListener");
  }
});

我注意到,当我将完整的表单放入 Bootstrap-Card-Body (如上面的代码中)时,该事件会按需要运行,并且附加的函数会在单击提交按钮时执行。

但是,当我将 Form-Submit 按钮放在 Bootstrap-Card-Footer 中(按照下面的代码)然后单击提交按钮时,附加的功能不会执行。

    <%= javascript_pack_tag 'photo', 'data-turbolinks-track': 'reload' %>
<div class="card text-center">
  <div class="card-header">
    Add New Photo
  </div>
  <div class="card-body">
    <%= form_for @photo do |f| %>
      <%= render "shared/errors", object: @photo %>
      <%= f.hidden_field :image, value: @photo.cached_image_data %>
      <%= f.label :title %>
      <%= f.text_field :title %>
      <%= f.label :image %>
      <%= f.file_field :image %>
      <% if @photo.image_data? %>
        <%= image_tag @photo.image_url(:medium) %>
        Remove attachment: <%= f.check_box :remove_image %>
      <% end %>
  </div>
  <div class="card-footer text-muted">
    <%= f.submit %>
    <% end %>
  </div>
</div>

这是它的样子。 卡体中移动了表单提交按钮

为什么会发生?我缺少什么概念?当我单击放置在卡片页脚中的提交按钮时,如何使附加的事件侦听器触发?

标签: javascriptruby-on-railsruby-on-rails-5

解决方案


在您示例的这一部分中:

<div class="card-body">
  <%= form_for @photo do |f| %>
  <%= render "shared/errors", object: @photo %>
  <%= f.hidden_field :image, value: @photo.cached_image_data %>
  <%= f.label :title %>
  <%= f.text_field :title %>
  <%= f.label :image %>
  <%= f.file_field :image %>
  <% if @photo.image_data? %>
    <%= image_tag @photo.image_url(:medium) %>
    Remove attachment: <%= f.check_box :remove_image %>
  <% end %>
</div>

<div class="card-footer text-muted">
  <%= f.submit %>
  <% end %>
</div>

在 Rails 完成将视图模板编译为 html 后,它看起来(大致)如下所示:

<div class="card-body">
  <form method="post" action="/photos" ...>
    <input ... />
    <input ... />
</div>

<div class="card-footer text-muted">
  <input type="submit" ... />
  </form>
</div>

它根本不是有效的 HTML。第一个 div (.card-body) 缺少结束</form>标记。但是第二个 div (.card-footer) 有一个意外的结束</form>标签。<form>浏览器仍然可以通过在第一个标签之前为您关闭标签来优雅地处理这个问题</div>,但是该<input type="submit" ... />按钮将位于表单之外,因此提交按钮将不再起作用。

我建议您更改代码,如下所示。只需让<form>标签围绕您的整张卡片:

<%= javascript_pack_tag 'photo', 'data-turbolinks-track': 'reload' %>

<div class="card text-center">
  <%= form_for @photo do |f| %>
    <div class="card-header">
      Add New Photo
    </div>

    <div class="card-body">
        <%= render "shared/errors", object: @photo %>
        <%= f.hidden_field :image, value: @photo.cached_image_data %>
        <%= f.label :title %>
        <%= f.text_field :title %>
        <%= f.label :image %>
        <%= f.file_field :image %>
        <% if @photo.image_data? %>
          <%= image_tag @photo.image_url(:medium) %>
          Remove attachment: <%= f.check_box :remove_image %>
        <% end %>
    </div>

    <div class="card-footer text-muted">
      <%= f.submit %>
    </div>
  <% end %>
</div>

推荐阅读