skip to Main Content

I am trying to build reusable dropdown with latest jQuery 3.6.1 and Bootstrap 5.2.3 but it has proven difficult.

I need to dynamically update the dropdown’s links with values from data attributes specified on the button that was clicked.

I am looking at the excellent solution provided by roko-c-buljan but it is using vanilla js and I need jQuery.
Below is my code by clicking on the Action buttons "…", I get an error:

{
  "message": "Uncaught TypeError: Cannot read properties of null (reading 'classList')",
  "filename": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.bundle.min.js",
  "lineno": 6,
  "colno": 44054
}

Code

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js" integrity="sha512-aVKKRRi/Q/YV+4mjoKBsE4x3H+BkegoM/em46NNlCqNTmUYADjBbeNefNxYV7giUp0VxICtqdrbqU7iVaeZNXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css" integrity="sha512-SbiR/eusphKoMVVXysTKG/7VseWii+Y3FdHrt0EpKgpToZeemhqHeZeLWLhJutz/2ut2Vw1uQEj2MbRF+TVBUA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
<body>
    <table class="table">
        <thead>
            <tr>
                <th>Type</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>item 1</td>
                <td>
                    <div class="dropdown">
                        <button type="button" class="btn btn-primary" data-type="ddbtn" data-id="1"  data-value="some value 1" data-bs-toggle="dropdown" aria-expanded="false" >...</button>
                    </div>
                </td>
            </tr>
            <tr>
                <td>item 2</td>
                <td>
                    <div class="dropdown">
                        <button type="button" class="btn btn-primary" data-type="ddbtn" data-id="2" data-value="some value 2" data-bs-toggle="dropdown" aria-expanded="false" >...</button>
                    </div>
                </td>
            </tr>
        </tbody>
    </table>

    <ul id="contextMenu" class="dropdown-menu">
        <li><a href="#" tabindex="-1" class="dropdown-item" id="link1">Action 1</a></li>
        <li><a href="#" tabindex="-1" class="dropdown-item" id="link2">Action 2</a></li>
    </ul>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.bundle.min.js" integrity="sha512-i9cEfJwUwViEPFKdC1enz4ZRGBj8YQo6QByFTF92YXHi7waCqyexvRD75S5NVTsSiTv7rKWqG9Y5eFxmRsOn0A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script>
    $(function () {
        $dropdown = $("#contextMenu"); // let's get the dropdown menu
        $("button[data-type='ddbtn']").click(function () {
            var id = $(this).data("id");
            console.log(id);

            $("#link1").attr("href","/action/dosomething?id=" + id);
            $("#link1").text($(this).data("value")); // just for test purposes.
            $("#link2").attr("href","/action/somethingelse?id=" + id);


            $(this).dropdown();
        });
    });
    </script>
</body>
</html>

2

Answers


  1. Try this

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css" integrity="sha512-SbiR/eusphKoMVVXysTKG/7VseWii+Y3FdHrt0EpKgpToZeemhqHeZeLWLhJutz/2ut2Vw1uQEj2MbRF+TVBUA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js" integrity="sha512-aVKKRRi/Q/YV+4mjoKBsE4x3H+BkegoM/em46NNlCqNTmUYADjBbeNefNxYV7giUp0VxICtqdrbqU7iVaeZNXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.bundle.min.js" integrity="sha512-i9cEfJwUwViEPFKdC1enz4ZRGBj8YQo6QByFTF92YXHi7waCqyexvRD75S5NVTsSiTv7rKWqG9Y5eFxmRsOn0A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    </head>
    <body>
        <table class="table">
            <thead>
                <tr>
                    <th>Type</th>
                    <th>Action</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>item 1</td>
                    <td>
                        <div class="dropdown">
                            <button type="button" class="btn btn-primary" data-type="ddbtn" data-id="1"  data-value="some value 1" data-bs-toggle="dropdown" aria-expanded="false" >...</button>
                        </div>
                    </td>
                </tr>
                <tr>
                    <td>item 2</td>
                    <td>
                        <div class="dropdown">
                            <button type="button" class="btn btn-primary" data-type="ddbtn" data-id="2" data-value="some value 2" data-bs-toggle="dropdown" aria-expanded="false" >...</button>
                        </div>
                    </td>
                </tr>
            </tbody>
        </table>
        <ul id="contextMenu" class="dropdown-menu">
            <li><a href="#" tabindex="-1" class="dropdown-item link1">Action 1</a></li>
            <li><a href="#" tabindex="-1" class="dropdown-item link2">Action 2</a></li>
        </ul>
    
        <script>
        $(function () {
            var $dropdown = $("#contextMenu");
    
            $("button[data-type='ddbtn']").each(function(){
                var id = $(this).data("id");
                var $menu = $dropdown.clone();
    
                $menu.find(".link1").attr("href","/action/dosomething?id=" + id);
                $menu.find(".link1").text($(this).data("value"));
                $menu.find(".link2").attr("href","/action/somethingelse?id=" + id);
                $(this).after($menu);
            });
        });
        </script>
    </body>
    </html>
    Login or Signup to reply.
  2. Using the first solutions of this related answer in vanilla JavaScript:
    simply assign a "shown.bs.dropdown" handler to every button and use dataset to get the data attribute values. Once you got your data values (by using const {id, value} = elBtn.dataset), use setAttribute() or textContent = to set the appropriate changes to your dropdown’s Anchor elements

    // DOM utility functions:
    const el = (sel, par) => (par || document).querySelector(sel);
    const els = (sel, par) => (par || document).querySelectorAll(sel);
    
    // Task: BS5 Popper fix for single static dropdown menu:
    const elDropdown = el('#contextMenu');
    const elsBtns = els(".optionsButton");
    const elDDLink1 = el("#link1");
    const elDDLink2 = el("#link2");
    
    const dropdownList = [...elsBtns].map((elBtn) => {
      const instance = new bootstrap.Dropdown(elBtn);
      instance._menu = elDropdown;
    
      // Add listener to clicked button calling dropdown,
      // and perform some dynamic changes on the dropdown's anchors:
      elBtn.addEventListener("shown.bs.dropdown", (evt) => {
        const {
          id,
          value
        } = elBtn.dataset;
        elDDLink1.setAttribute("href", "/action/dosomething?id=" + id);
        elDDLink1.textContent = value; // just for test purposes.
        elDDLink2.setAttribute("href", "/action/somethingelse?id=" + id);
      });
    
      return instance;
    });
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    
    
    <table id="myTable" class="table table-hover">
      <thead>
        <tr>
          <th>#</th>
          <th>Document</th>
          <th>Reference</th>
          <th>Action</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>1</td>
          <td>General Policies</td>
          <td>GP-01-2022</td>
          <td>
            <div class="dropdown">
              <button type="button" class="btn btn-primary optionsButton" data-type="ddbtn" data-id="1" data-value="some value 1" data-bs-toggle="dropdown" aria-expanded="false">...</button>
            </div>
          </td>
        </tr>
        <tr>
          <td>2</td>
          <td>Training Material</td>
          <td>GP-02-2022</td>
          <td>
            <div class="dropdown">
              <button type="button" class="btn btn-primary optionsButton" data-type="ddbtn" data-id="2" data-value="some value 2" data-bs-toggle="dropdown" aria-expanded="false">...</button>
            </div>
          </td>
        </tr>
      </tbody>
    </table>
    
    
    <ul id="contextMenu" class="dropdown-menu">
      <li><a href="#" tabindex="-1" class="dropdown-item" id="link1">Action 1</a></li>
      <li><a href="#" tabindex="-1" class="dropdown-item" id="link2">Action 2</a></li>
    </ul>
    
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search