1

I have some buttons and content made dynamically from my database. I need to be able to press a button and have it toggle the content in the associated <pre>.

I am able to get jQuery to have click events with each button, but it only shows the content of the most recently created <pre>.

I just don't know how to get each button to interact with the correlating <pre> tag. Any help would be appreciated.

echo "<div class='my-buttons'>";
for ($j = 0; $j < $num; ++$j)
{
  $row = $result->fetch_array(MYSQLI_ASSOC);
  echo "<button id=title>".$row['title']."</button>";
  $code = base64_decode($row['code']);
  echo "<pre style='display:none' id='code'>$code</pre>";        
}
echo "</div>
$('.my-buttons').on('click', (e) => $('#code').slideToggle('slow')))
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
sabadoosh
  • 23
  • 3
  • 1
    "Dynamically made" *by php* is not dynamically made. Your issue is that they all have the same `id=code`, so `$("#code")` will always give you the first one. – freedomn-m Aug 16 '21 at 15:25
  • Also for future questions about JS, it's much better to include the actual HTML output instead of the PHP which isn't relevant to the issue. – Rory McCrossan Aug 16 '21 at 15:28

2 Answers2

3

There's two main issues here. Firstly you apply id attributes to the HTML elements you create in your PHP loop. As such, you are duplicating them which is invalid. There can only ever be 1 element in the DOM with a given id. Change these to classes instead.

Then within your jQuery code you need to use DOM traversal to find the pre element related to the clicked button, not target all pre elements at once. Given the HTML structure you have, next() will do this for you:

$('.my-buttons').on('click', e => $(e.target).next('.code').slideToggle('slow'));
pre.code { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='my-buttons'>
  <button class="title">title 1</button>
  <pre class="code">Code 1... </pre>
  
  <button class="title">title 2</button>
  <pre class="code">Code 2... </pre>
  
  <button class="title">title 3</button>
  <pre class="code">Code 3... </pre>
  
  <button class="title">title 4</button>
  <pre class="code">Code 4... </pre>
  
  <button class="title">title 5</button>
  <pre class="code">Code 5... </pre>
</div>

Also note the use of external CSS to apply the display: none to the pre elements. Inline styling using the style attribute should be avoided where possible as it ties the HTML and CSS together too closely.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
0

If you have dynamically created/changed element (after DOM loading) you can use following code:

$(document).on('click','#exampleID',function(){
//do something
});
rince
  • 123
  • 7
  • 2
    I also considered that (and would close vote as a duplicate of [event delegation](https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) ) - but the "dynamically created elements" are not created by js, rather by php (so not "dynamic" as we would term them). This can be ruled out as OP states *but it only shows the content of the most recently created `
    `* (so the click event is fine)
    – freedomn-m Aug 16 '21 at 15:39