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 >
<thead>
<tr>
<th>Type</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>item 1</td>
<td>
<div >
<button type="button" 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 >
<button type="button" 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" >
<li><a href="#" tabindex="-1" id="link1">Action 1</a></li>
<li><a href="#" tabindex="-1" 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>
CodePudding user response:
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 >
<thead>
<tr>
<th>Type</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>item 1</td>
<td>
<div >
<button type="button" 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 >
<button type="button" 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" >
<li><a href="#" tabindex="-1" >Action 1</a></li>
<li><a href="#" tabindex="-1" >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>
CodePudding user response:
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" >
<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 >
<button type="button" 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 >
<button type="button" 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" >
<li><a href="#" tabindex="-1" id="link1">Action 1</a></li>
<li><a href="#" tabindex="-1" 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>