【问题标题】:Cancel/prevent Bootstrap5 collapse when clicking inside links/buttons单击内部链接/按钮时取消/防止 Bootstrap5 崩溃
【发布时间】:2021-09-04 23:05:24
【问题描述】:

我有一个包含父行的表,其中包含隐藏的子行。这些子行使用引导折叠机制显示/隐藏。单击父行可切换子行的折叠。可以动态创建父行及其子行。

父行可以包含链接和按钮。单击这些时,我想取消/防止折叠切换。下面给出一个简单的最小示例。

这里提出了类似的问题:stackoverflow - prevent bootstrap collapse from collapsing

event.stopPropgation(); 似乎不起作用(见下文),即使直接定位链接/按钮也不行(无论如何这可能对动态创建的元素没有帮助)。

我尝试听collapse events from Bootstrap 并使用.toggle() 方法撤消折叠,但这(显然)会导致递归事件。

有没有一种简单的方法来防止折叠触发行内的链接/按钮切换折叠?

$("#createNewRow").on("click", function() {
    var number = Math.round(Math.random() * 100000);
  new_row = `
    <tr data-bs-toggle="collapse" data-bs-target=".row`+number+`-child">
        <td>
        This is a dynamically created parent row. Click me to toggle childs.
        <a class="child-link" href="!#">A Link!</a>
        <button class="child-button">A button!</button>
      </td>
    </tr>
  <tr class="collapse child row`+number+`-child"><td>I'm a child row!</td></tr>
  <tr class="collapse child row`+number+`-child"><td>I'm another child row!</td></tr>
  <tr class="collapse child row`+number+`-child"><td>I'm yet another child row!</td></tr>
  `;
  $("#main-table").append(new_row);
});

$(".child-link").on("click", function(e) {
    console.log("The link was clicked!");
  e.stopPropagation();
});

$(".child-button").on("click", function(e) {
    console.log("The button was clicked!");
  e.stopPropagation();
});

$(document).on("click", ".child-link", function(e) {
    console.log("The link was clicked!");
  e.stopPropagation();
});

$(document).on("click", ".child-button", function(e) {
    console.log("The button was clicked!");
  e.stopPropagation();
});
tr {
  background-color: #fcf;
}

.child {
  background-color: #efd;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css">

<div class="container">
  <table class="w-100" id="main-table">
  <tr data-bs-toggle="collapse" data-bs-target=".row1-child">
    <td>
      This is a parent row. Click me to toggle childs.
      <a class="child-link" href="!#">A Link!</a>
      <button class="child-button">A button!</button>
    </td>
  </tr>
  <tr class="collapse child row1-child"><td>I'm a child row!</td></tr>
  <tr class="collapse child row1-child"><td>I'm another child row!</td></tr>
  <tr class="collapse child row1-child"><td>I'm yet another child row!</td></tr>
  </table>
</div>

<button class="mt-4" id="createNewRow">Create a new set of rows!</button>

【问题讨论】:

  • 最小示例直接属于您的问题,而不仅仅是转储到像 jsfiddle 这样的外部平台上。请相应地进行编辑。
  • @CBroe 感谢您的评论,我已将示例添加到问题中。
  • 我猜如果您不通过data- 属性自动触发该功能可能会更容易,而是自己处理它,通过可用的JS函数进行折叠切换getbootstrap.com/docs/5.0/components/collapse/#methods如果将其与要用作触发器的表行的单击处理程序结合使用,则应该能够在执行实际切换之前检查事件目标。
  • 这里有些特殊情况,因为这里基本上“嵌套”了 interactive 元素。 Bootstrap 通常使用abutton 作为触发元素——你不能在其中放置任何额外的交互元素,HTML 只是禁止这样做。您通过使用 tr 作为触发元素来“解决”该问题 - 默认情况下不是交互式元素,因此 HTML 规则 allow this, [...]
  • [...] 但最终效果是相同的 - 其他可点击元素中的可点击元素,这不是关于可访问性的最佳想法。所以我猜你必须忍受 Bootstrap 不支持这个开箱即用的功能,因为它只是一个特例。 (说到可访问性,将tabindex 添加到这些表行可能是个好主意,这样至少可以使用键盘导航来访问它们。)

标签: javascript bootstrap-5


【解决方案1】:

这是一个很好的问题!事件的传播很棘手,

您需要有条件地分配一个事件处理程序,以防止 Bootstrap 折叠事件(showhide)发生。 Collapse 事件在父 tr 被点击时发生。

var eventHandler = function (e) {
     console.log("The collapse event was prevented!", e);
     e.preventDefault();
     e.stopPropagation();
}

// initially prevent collapse from toggling
$(".row1-child").on("show.bs.collapse", eventHandler)

// prevent the click event on child links
$(".child-link").on("click", function(e) {
    console.log("The link was clicked!");
    e.stopPropagation();
    e.preventDefault();
});

// prevent the click event on child buttons
$(".child-button").on("click", function(e) {
    console.log("The button was clicked!");
    e.stopPropagation();
    e.preventDefault();
});

// when the parent row is clicked manually toggle the collapsible elements and re-attach event listeners
$("[data-bs-toggle]").on("click", function(e) {    
    console.log("The parent was clicked! dispatch");
    $(".row1-child").off("show.bs.collapse", eventHandler)
    $(".row1-child").off("hide.bs.collapse", eventHandler)
    $(".row1-child").collapse('toggle')
    $(".row1-child").on("show.bs.collapse", eventHandler)
    $(".row1-child").on("hide.bs.collapse", eventHandler)
});

Demo

【讨论】:

  • 感谢您的回答!我已经尝试过演示,我认为这不适用于动态创建的行。另外,是否有同时使用 .stopPropagation() 和 .preventDefault() 的理由?
  • “我认为这不适用于动态创建的行”..是的,这超出了您的问题范围。在“createNewRow”中创建行后添加点击处理程序
猜你喜欢
  • 1970-01-01
  • 2020-05-31
  • 2014-04-07
  • 2018-10-13
  • 1970-01-01
  • 2018-01-23
  • 1970-01-01
  • 2012-02-17
  • 1970-01-01
相关资源
最近更新 更多