Avoid Bootstrap 5 collapse when clicking on links or buttons

In my table, there are parent rows with hidden child rows that can be toggled using the bootstrap collapse feature. Clicking on a parent row toggles the visibility of its child rows. Both parent and child rows can be dynamically added to the table.

Parent rows may contain links and buttons, and I want to prevent the collapse toggle when these links or buttons are clicked. An example is provided below:

A related question was posted on Stack Overflow: stackoverflow - prevent bootstrap collapse from collapsing

Using event.stopPropagation(); does not seem to work, even when targeting the link/button directly. It also does not address the issue with dynamically created elements. I tried listening to the collapse events from Bootstrap and using the .toggle() method to reverse the collapse, but this triggers a recursive event.

Is there a straightforward way to prevent links/buttons within the collapse-triggering row from toggling the collapse?

$("#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/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f1939e9e858285839081b1c4dfc1dfc0">[email protected]</a>/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/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a7c5c8c8d3d4d3d5c6d7e79289978996">[email protected]</a>/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>

Answer №1

What a fascinating question! Navigating event propagation can be quite challenging,

It's important to carefully assign event handlers that can control the Bootstrap collapse events (show and hide). The Collapse event should only trigger when the parent tr is clicked.

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

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

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

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

// Manually toggle collapsible elements and re-attach event listeners when parent row is clicked
$("[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)
});

Check out the Demo

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to sort a table using a dropdown menu selection as a filter?

I am currently working on a project that involves a table with three columns, which are typically populated from a SQL database. My goal is to filter the third column based on the value selected from a dropdown menu. I came across a helpful tutorial on W3 ...

The Response.Write function is not functioning properly in the production environment

I have created a C# WebService (ASMX) with the code snippet below: if (!SomeValidation()) { //context.Response.ContentType = "application/json"; //context.Response.ContentType = "text/plain"; context.Response.ContentType = "application/text"; ...

Adjust the counter by increasing or decreasing based on the selection or deselection of tags

Currently, I am utilizing Next.js to manage a question form that consists of multiple questions with multiple answers. Users have the option to select one or multiple tags for each question. When a user selects one or more tags to answer a question, it sho ...

Panel that collapses and increments its ID each time within my loop

I have a Collapsible Panel with this header, <div id="CollapsiblePanel1" class="CollapsiblePanel"> <div class="CollapsiblePanelTab" tabindex="0">Comments</div> <div class="CollapsiblePanelContent"> Content &l ...

I'm curious about the origin and purpose of req.user - where does it come from and

Recently, I've been delving into Nestjs and found myself a bit puzzled by the req.user. Where does this come from and do we have to manually request it? What exactly is req.user and what advantages does it offer? Must I assign payload to it manually? ...

What is preventing this from functioning properly? (html/javascript)

I need help checking if this code is correct, as I am not very knowledgeable about HTML. I would appreciate it if someone could explain it to me in simple terms so I can understand. Here is the code: <input type="text" id="user" value=""> <inpu ...

Setting a validation message for a Vuejs username input while enforcing a maximum character limit

<script> export default { name: "Register", props: { msg: String, }, }; </script> <style scoped> * { box-sizing: border-box; } div { padding: 0; margin: 0; font-family: system-ui; } .red { color: red; } <template& ...

Can process.env.NODE_ENV be found within Azure App Service?

I am integrating NodeJS with my Angular application using ExpressJS. I came across an npm package called norobot that I want to install in order to utilize the process object. I need guidance on how and where to set the NODE_ENV in an App Service on Micro ...

What sets apart computed, state, and action in MobX?

Currently, I am delving into MobX and grappling with the concepts of computed, state, and action individually. Do they serve similar purposes? One aspect of MobX that intrigues me is deciphering the disparity between computed properties and state. My unde ...

The router.navigate() function seems to be malfunctioning as it is not working as

I have a method defined as follows: private redirect(path: string): void { this.router.navigate([path]); } This method is called within another method like so: private onError(error: any): void { switch (error.status) { case 401: / ...

Can someone provide guidance on creating a calculator using the Switch statement in Javascript?

Introduction to HTML: <div id="content"> <div id="calculator-container"> <form name="calc"> <!-- The form is named "calc" --> <label for="output">A Simple Calculator</label> & ...

Is the unit-converts npm package compatible with the website https://unpkg.com?

Having issues importing the npm package 'convert-units' using unpkg, I attempted the following method: <script src="unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="02616d6c746770762f776c6b767142302c31 ...

Error encountered: Denied access in AWS Transcription Node JS API

I have been working with the AWS transcription API in Node JS and my code looks like this: const tClient = new TranscribeClient({ region: "us-east-1", credentials: { accessKeyId: AWS_ID, secretAccessKey: SECRET, ...

Utilizing JSON data from Google Maps Matrix with JavaScript

I am trying to fetch the real-time duration of a particular route on Google Maps through my JavaScript code. However, I seem to be stuck. Here's what I have written so far: $(document).ready(function Duration() { var d = new Date(); $.ajax({ ...

What is the method for obtaining a dynamic image URL for the <a href> link?

Here is the default Wordpress generated code for displaying images: <div class="image-section"> <a href="http://websitename.com/wp-content/uploads/2019/06/image-1.jpg" target="_blank" rel="noopener noreferrer"> <img src="http://websit ...

Exploring Objects without the need for loops

Currently, I am focusing on optimizing the performance of the following objects: var scheduleFee = { poor = {level1:25,level2:25,level3:25} , good = {level1:15,level2:20,level3:25} , vgood = {level1:10,le ...

Using jQuery's slideToggle feature to hide content when clicked again or when a different button is

I have a challenge with creating toggle buttons that require specific functions: 1) Display content on the first click (this is working) 2) Conceal content when another button is clicked (this is also working) 3) Hide content on the second click (this i ...

Retrieving a designated set of attributes for elements chosen using an element selector

Is there a way to retrieve specific attributes for the first 10 <p> elements in a document using jQuery? I know I can easily get the first 10 elements with $('p').slice(0,10), but I only need certain attributes like innerText for each eleme ...

Developing a dynamic modal using Angular and embedding Google Maps within an iframe

I'm currently working on implementing a modal in my Angular application that, when opened, displays Google Maps within an iframe. The problem I'm facing is that the iframe isn't loading and I'm receiving this error in the browser conso ...

Guide to correcting Form Data errors with XHR resulting in a 400 Bad Request

This is a straightforward piece of code I've written. It's simply a POST request to my API endpoint using FormData. Interestingly, the API is returning a bad request error for reasons unknown to me. When I tested the API with curl, everything wo ...