bootstrap: suppress modal from within show.bs.modal event

Viewed 424

Is it possible to tell bootstrap to NOT show the modal, by returning a false to the framework from within the show.bs.modal event?

EDIT:

Using stopPropagation() or simply disable a button is not what I want. I want to process the logic inside show.bs.modal event. Because show/hide the modal is a dynamic decision.

Of course, it is possible to do this logic outside of the event and programatically call $('#modal').show(), if this is the only way.

1 Answers

June 23, 2021 — Updated Answer

When this question was originally asked (May 13, 2021), it was not possible to stop a modal from being shown from within the show.bs.modal event handler more than once.

That’s because there was a bug in all of the Bootstrap releases, from V4.0.0 to V5.0.1 (V3 did not have the problem). An issue report outlining the problem was filed and Pull Requests for V4 and V5 were created.

With Bootstrap V5.0.2, the problem has been fixed as the snippet below illustrates. Returning event.preventDefault() (for V5.0.2 and above) in response to the show.bs.modal event will prevent a modal from being displayed. Not returning the preventDefault() in response to a follow-on event will display the modal.

var modalCheckbox = document.getElementById('modalSwitch');
var modalCheckboxLabel = document.getElementById('modalLabel');
var modalPreventDefault = false;
var myModal = document.getElementById('myModal');

modalCheckbox.addEventListener('change', (event) => {
    if (event.currentTarget.checked) {
        modalPreventDefault = false;
        modalCheckboxLabel.innerHTML = 'Modal Enabled';
    } else {
        modalPreventDefault = true;
        modalCheckboxLabel.innerHTML = 'Modal Disabled';
    }
});

myModal.addEventListener('show.bs.modal', (event) => {
    console.log('Modal: ' + modalPreventDefault);
    if (modalPreventDefault === true) {
        return event.preventDefault();
    }
});
li {
    margin-bottom: 0.375rem;
}

code {
    font-size: 1em;
}

.btn {
    width: 11rem;
}

.form-switch .form-check-input {
    cursor: pointer;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js"></script>

<div class="container mt-5">
    <h2 class="text-center">Bootstrap <code>show.bs.modal</code> test case &ndash; V5.0.2</h2>
    <div class="row justify-content-evenly">
        <div class="col-6 col-md-4 col-lg-3">
            <h3>Modal demo</h3>
            <div class="form-check form-switch mb-3">
                <input id="modalSwitch" class="form-check-input" type="checkbox" checked autocomplete="off">
                <label id="modalLabel" class="form-check-label font-italic" for="modalSwitch">Modal Enabled</label>
            </div>
            <!-- Button trigger modal -->
            <button id="modalButton" class="btn btn-primary" type="button" data-bs-toggle="modal" data-bs-target="#myModal">
                Show Modal
            </button>
        </div>
    </div>
</div>

<div class="container my-5">
    <div class="row justify-content-center">
        <div class="col-sm-11 col-md-9 col-lg-7">
            <h3>Bootstrap Issue &mdash; Resolved</h3>
            <p><a href="https://github.com/twbs/bootstrap/issues/34055" title="Put real link here!">Issue:</a> Modal event.preventDefault() for show.bs.modal: disables modal with fade class from being displayed again in V4 & V5 (up to V5.0.1).</p>
                
            <p>The JavaScript for Bootstrap V4 & V5 (up to V5.0.1) stopped a modal from being displayed again, once displaying the modal has been prevented using <code>event.preventDefault()</code>.</p>
            <p>The problem has been corrected in V5.0.2.</p>
            <ul>
                <li>A listener is attached to listen for the <code>show.bs.modal</code> event.</li>
                <li>The checkbox switch setting allows or prevents the modal to be displayed:
                    <ul>
                        <li>If the checkbox is checked (Modal Enabled), the listener does nothing and the modal is displayed.</li>
                        <li>If the checkbox is un-checked (Modal Disabled), the listener returns <code>event.preventDefault()</code> and nothing is displayed.</li>
                    </ul>
                </li>
            </ul>
                <p>In previous Bootstrap V5 versions (&amp; V4), re-checking the checkbox (re-enabling) did not enable the modal to again be displayed after the modal was disabled. The <code>event.preventDefault()</code> now works as expected.</p>
        </div>
    </div>
</div>

<!-- Modal -->
<div id="myModal" class="modal fade" tabindex="-1" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 id="myModalLabel" class="modal-title">Modal title</h5>
                <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                ...
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>

Update June 9, 2022

Bootstrap V4.6.1 was released last year (October 28, 2021). event.preventDefault() for show.bs.modal now works as expected. Refer to this JSBin demo to see it in operation.

Related