防止 Bootstrap 模态框在按钮点击时弹出

24

我有一个页面,其中包含多个Bootstrap模态框,每个模态框都有:

data-toggle="modal" data-target="#modal-12345"

问题是,我有一整行表格是可点击的,例如:

<tr data-toggle="modal" data-target="#modal-12345">

模态内容在另一个隐藏的表格行中,紧随其后的是下一个可点击的行,如此往复。现在,该行还包含一个按钮,当单击时将转到另一个页面。

我需要整行都可以点击以打开模态框,除非单击去往其他页面的按钮,然后我需要阻止模态框的打开。

我需要类似这样的东西

<script>
$('.ID').on('click', '.btn', function(e) { e.stopPropagation(); })
</script>

但是,针对这个:

data-toggle="modal"

我还尝试过给TR加上一个“modaltoggle”类,然后用JavaScript调用它,但那也没起作用。

4个回答

22

为不想触发模态框的项目添加某种标识符,例如类似于 no-modal 的类,然后在你的 jQuery 中添加模态框的 show.bs.modal 事件代码。获取相关元素,即触发事件的元素,然后查看它是否具有所需的类。如果有,则运行 e.stopPropagation()

BOOTPLY

jQuery:

$('#myModal').on('show.bs.modal', function (e) {
  var button = e.relatedTarget;
  if($(button).hasClass('no-modal')) {
    e.stopPropagation();
  }  
});

HTML

<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
  Launch demo modal
</button>

<button type="button" class="btn btn-primary btn-lg no-modal" data-toggle="modal" data-target="#myModal">
  Launch demo modal
</button>

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
        <h4 class="modal-title" id="myModalLabel">Modal Header</h4>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

正如您所看到的,第二个按钮有一个名为no-modal的类。当点击该按钮时,jQuery会检查该类是否存在,如果存在,则防止模态框弹出。点击第一个按钮会导致模态框正常弹出,因为它没有该类。

Bootstrap模态框由页面上的元素触发时会触发特定事件,从它们被触发的那一刻到完全弹出的那一刻。您可以通过在官方文档中查看Bootstrap模态框的事件部分了解有关这些事件的信息,以了解您可以使用它们的用途。


14
这个答案是不正确的。它之所以“起作用”,只是因为stopPropegation未定义,从而停止执行。正确的调用应该是stopPropagation,而不是e,但我已经尝试过了;仅使用stopPropagation无法有效地防止弹出对话框。实际上,AoN的解决方案更接近正确。我不确定为什么它被投票下降,因为"return false;"确实可以正确地停止执行并防止对话框弹出。如果你在事件处理程序中添加return false; 跟在stopPropagation之后,它会正常工作。(事实上,即使没有使用stopPropagation调用,它也能正常工作。) - thesentiment
是的,我也尝试过这个--在其中一个单元格中放置一行和一个按钮的情况下,e始终指的是行而不是按钮。 - Tony Hinkle
我尝试了 e.stopPropegation(); 但它对我没用。我使用了 e.preventDefault(); 和 e.stopImmediatePropagation(); 就可以了。 - nntona
1
你打错字了,stopPropegation 应该是 stopPropagation。 - izzy
在Bootstrap 3中,只有e.preventDefault();return false;可以正常工作。但请注意,如果您有一个处理程序,在打开模态框之前将模态框的ID添加到URL哈希中,那么您可能需要首先删除它(location.hash=''; return false;),否则什么也不会起作用。 - Radek Pech

17
$('#myModal').on('show.bs.modal', function (e) {
 return e.preventDefault(); 
});

或者

<button type="button" class="custom" data-toggle="modal" data-target-custom="#myModal">Launch demo modal</button>
<script>
target = $(".custom").attr('data-target-custom');
if(condition) {
 $(target).modal('show');
}
</script>

e.stopPropagation(); 或 e.preventDefault(); 如果您重新打开模态框或页面中使用多个模态框,则它将无效。


代码片段和解释是一个非常好的结合! - Sahil Mahajan Mj
e.preventDefault 不起作用 - HelloNewWorld
因为评论中提到“如果要重新打开模态框,e.stopPropagation()或e.preventDefault()将无效”,所以我点了赞。在我的用例中,由于重复使用模态框,这是一个问题。相反,return false 就解决了问题。(BS 4.6) - Aaron Dunigan AtLee
重新打开模态框的问题似乎是由BS4中的一个错误引起的:https://stackoverflow.com/a/67521199 - Aaron Dunigan AtLee

15

这是一个JSFiddle演示,用于展示我要解释的内容:http://jsfiddle.net/68y4zb3g/

就像MattD所解释和演示的那样,阻止模态窗口的启动相当简单,尽管他的示例适用于标准模态应用程序。由于您在脚本代码中使用了.btn,我假设您将其应用于所有相关按钮。我还假设您的模态代码与Bootstrap演示页面上的类似。如果您提供实际的表格代码,我可以根据您已有的代码进行具体的调整。

$('tr .btn').on('click', function(e) {
   e.stopPropagation();
});
td {
    border: 1px #000000 solid;
    padding: 10px;
}
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="http://getbootstrap.com/dist/css/bootstrap-theme.min.css" rel="stylesheet"/>
<script src="http://getbootstrap.com/assets/js/ie-emulation-modes-warning.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>

<table>
    <tr data-toggle="modal" data-target="#modal-12345">
        <td>Launch modal 12345</td>
        <td><button id="btn-12345" class="btn">12345</button></td>
    </tr>
    <tr>
        <td colspan="2" class="modal fade" id="modal-12345" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                        <h4 class="modal-title" id="myModalLabel">Modal title</h4>
                    </div>
                    <div class="modal-body">
                        12345
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                    </div>
                </div>
            </div>
        </td>
    </tr>
</table>

注意:我用TD替换了通常充当模态框外部包装器的DIV,并添加了一小段CSS代码,以使内容分离更加清晰。

通过使用应用于所有按钮的类,您不必为每个ID编写一个函数。话虽如此,我建议使用自定义类作为触发器。.btn是Bootstrap核心中的标准类,因此请尝试使用.modalBtn,以防止与合法的Bootstrap功能发生冲突。

希望对您有所帮助。^^


这个答案是更正确的答案,值得被标记为解决方案。我唯一的评论是它比 OP 要求的多了一点。也许它被投票反对是因为它部分不相关。 - thesentiment
1
我也在尝试使用这个解决方案。一旦模态框被阻止了一次,它就不会再次打开。在打开模态框之前,我进行了一些小的验证,如果验证失败,我不希望模态框打开。我想要向用户警告错误,一旦他们修复了错误,模态框应该能够打开。 - Brent Connor
@BrentConnor 很好的发现。老实说,我没有注意到这一点。我已经修改了脚本,使其忽略对 TR 的点击,而不是试图阻止 .modal 的启动。 - Christopher Esbrandt
@AoN,你能帮我解决一下我的问题吗? - Brent Connor

2
从你的代码中删除以下行: data-toggle = "modal"
然后,在你的函数中完成验证后,写入以下代码:
$('#myModal').modal({
   show: true
});

未捕获的错误:MODAL:选项“show”的类型为“string”,但期望的类型为“boolean”。 也许应该去掉周围的''。 - sergiol
我刚刚确认了我的先前评论,确实没有使用''。已经为您修复了。 - sergiol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接