检查后的复选框会在jquery中丢失其监听器

时间:2015-05-05 04:40:46

标签: javascript ruby-on-rails

以下是我在rails视图中的代码:

<div class="lists">
  <h1>Your Todo Lists</h1>
  <div class="incomplete-list">
    <p>This is the incomplete list</p>
    <% @incomplete_list.items.each do |item| %>
    <div class="incomplete-item">
      <%= form_for :item, url: item_path(item), method: :post, html: { class: "item-box" } do |f|%>
        <%= f.label item.title %>
        <%= f.check_box item.id %>
      <% end %>
    </div>
    <% end %>
  </div>

  <div class="complete-list">
    <p>This is the completed list</p>
    <% @complete_list.items.each do |item| %>
    <div class="complete-item">
      <%= form_for :item, url: item_path(item), method: :post, html: { class: "item-box" } do |f|%>
        <%= f.label item.title %>
        <%= f.check_box item.id %>
      <% end %>
    </div>
    <% end %>
  </div>
</div>


<script>
  $(document).ready(function() {
    var changeDom = function(itemRow) {
      var parentList = itemRow.parent()
      itemRow.remove()
      // I am so dumb, you can't remove an itemRow first and then ask for its parent. You dumb dumb. It's [] if you
      // ask for the parent after you remove it. So you need to set it first with var parent =
      if (parentList.attr("class") === "incomplete-list") {
        $(".complete-list").append(itemRow)
      }
      else {
        $(".incomplete-list").append(itemRow)
      }
    }

    var itemLists = $(".lists")
    itemLists.find(":checkbox").on("change", function(box){
      var box = $(this)
      var item_number = parseInt(box[0].name.match(/[^[\]]+(?=])/g)[0])
      $.ajax( { type: "PUT",
          url: "items/" + item_number,
          data: { id: item_number },
          success: function(text) {
            changeDom($(box[0].closest("div")))
          }
        });
      })
    })
</script>

它第一次运作。我使用不完整的项目和完整项目呈现此页面。但是在我点击它们并且从一个列表跳到另一个列表之后......他们失去了听众而不再工作。一个人做什么?

另外,如果选中一个不完整的框,我会在另一个列表中检查它,并且当一个复选框位于完整列表中时,它将在另一个框中取消选中。

2 个答案:

答案 0 :(得分:2)

如果你删除了一个dom元素,那么它也会删除它的听众。

你可以做两件事:

  1. 您的changeDom功能可以修改,因此它不会删除该元素,而是应该元素从一个列表移动到另一个列表。如果移动元素,则仍将绑定侦听器。

    查看jQuery中的detach方法,作为移动元素的一种方法,但保持它的侦听器绑定

    https://api.jquery.com/detach/

  2. 但更好的方法是更实际地将事件绑定到列表中的每个复选框/行。

    相反,使用事件委派来绑定更高级别的单击事件。哪个更有效,因为您不必为每个复选框创建侦听器。相反,整个列表只有一个监听器 - 但它仍然会响应每个复选框的点击次数。

    $(".lists").on("change", ":checkboxes", function() {
       // do stuff
    });
    

    因为您正在倾听更高级别的事件,所以如果您移动复选框元素也不重要 - 没有事件侦听器会被中断。

    以下是有关事件委派的一些文档:

    https://learn.jquery.com/events/event-delegation/

答案 1 :(得分:0)

问题是使用.remove()将删除附加的事件处理程序和数据

  

除了元素本身,所有绑定事件和jQuery   与元素关联的数据将被删除

在你的情况下,因为在删除后元素被添加到一个或另一个元素,所以不需要调用com.plivo.example.outbound.Call你只需将它附加到目标元素

remove()

如果您仍想遵循相同的流程,请使用detach()

var changeDom = function (itemRow) {
    var parentList = itemRow.parent()
    if (parentList.attr("class") === "incomplete-list") {
        $(".complete-list").append(itemRow)
    } else {
        $(".incomplete-list").append(itemRow)
    }
}