How to add a eventListener for each post (without using jQuery)?

Viewed 76

I'm working on a code where the user can fetch user posts in a list of post titles. If the user clicks on a post title then there should show up a new div box with more information. The posts are fetched with php and the post description will fetched by AJAX. (later i will fetch the posts also with AJAX)

My Problem: Only the first post title works and by clicking it, all post description show up in 1 div box. I think I need an array, and was trying it with no success.

What It Should Do: For example by clicking on title: 2, only the description of post 2 should show up.
And remember, the post title list is dynamic and are fetched data from database.

Here is my code:

INDEX.PHP

<!DOCTYPE html>
<html>
  <head>
    <title>XY</title>
    <meta charset="UTF-8"/>
  </head>

  <body>
    <?php
    $db = mysqli_connect("localhost", "root", "", "xy");
    $result = mysqli_query($db, "SELECT * FROM images");
      while ($row = mysqli_fetch_array($result))
      {
          echo "<div class='img_title'><button id='img_descr'><a>Title: <b>".$row['img_title']."</b></a></button></div>";
      }
    ?>
    <div id="descrs"></div>
    <script>
      document.getElementById('img_descr').addEventListener('click', loadDescr);

      function loadDescr(){
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'ajax.php', true);

        xhr.onload = function(){
          if(this.status == 200){
            var descrs = JSON.parse(this.responseText);

            var output = '';

            for(var i in descrs){
              output += '<ul>' +
                '<li class="ajax_img_descr">ID: '+descrs[i].img_descr+'</li>' +
                '</ul>';
            }
            document.getElementById('descrs').innerHTML = output;
          }
        }
        xhr.send();
      }
    </script>
  </body>
</html>

AJAX.PHP

<?php
// Create Connection
$conn = mysqli_connect('localhost', 'root', '', 'xy');
$query = 'SELECT * FROM images';
// Get Result
$result = mysqli_query($conn, $query);
// Fetch Data
$users = mysqli_fetch_all($result, MYSQLI_ASSOC);
echo json_encode($users);
?>

Database Structure/Content:

  1. Create a database called "xy"
  2. Create a table called "images":

    CREATE TABLE images (
        img_id int(11) not null AUTO_INCREMENT PRIMARY KEY,
        img_file varchar(250) not null,
        img_title text(50) not null,
        img_descr varchar(250) not null
    );
    
  3. Insert data to database:

    INSERT INTO images (img_title, img_descr) VALUES ('Golden Retriever', 'UK:DFYDFBAERSDFBYDFBYDFydfbydfBaeydfb1311y');
    INSERT INTO images (img_title, img_descr) VALUES ('Appenzeller Sennenhund', 'Swiss:erydfydfbrehaydydfbydfydbaerydf2ydfb');
    INSERT INTO images (img_title, img_descr) VALUES ('German Shepard', 'Germany:ydf3d1fby3df1by3dfb6ydfb31ydf31ydf');
    INSERT INTO images (img_title, img_descr) VALUES ('Alaskan Klee Kai', 'USA:f3ngxfgxfgnxfxfgnxfg3xf31gnxfgner6ae13')
    
1 Answers

You are using same ID img_descr for all buttons. That's why it will work for the first button's event only and not for others.

Try using the class for those buttons or unique ids. Below is the example of using a common class for those buttons. document.querySelectorAll will return all buttons with class "img_descr" as NodeList(DOM Node List) which is an array kind, you can iterate over it using the loop.You can use CSS Selectors .(dot) class / # for (id) here.

Here is the example, it is working on my pc. hope it works on yours too!!

<!DOCTYPE html>
<html>
  <head>
    <title>XY</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <?php
       $db     = mysqli_connect("localhost", "root", "", "xy");
       $result = mysqli_query($db, "SELECT * FROM images");
       while ($row = mysqli_fetch_array($result)) {
          // changed <button id='img_descr'> to <button class='img_descr'>
          echo "<div class='img_title'><button class='img_descr'><a>Title: <b>" . $row['img_title'] . "</b></a></button></div>";
       }
     ?>
     <div id="descrs"></div>
     <script>
       // Get the buttons (NodeList)
       var buttons = document.querySelectorAll("button.img_descr"); 
       console.log(buttons); // debugging in JS!! press F12, see console tab!

       for(var x=0; x < buttons.length; x++) {
         buttons[x].addEventListener('click', loadDescr);
       }

       // getElementById returns only one element with the id passed as input
       // which is the first found node with the id in the DOM.
       // document.getElementById('img_descr').addEventListener('click', loadDescr);

     function loadDescr(e) {
        // here e is the event and you can get the source of the event(button) by
        // e.target target. Here target would be the button that you clicked.
        console.log(e.target.innerHTML); // use console.log() very often in JS code!
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'ajax.php', true);

        xhr.onload = function() {
           if (this.status == 200) {
             var descrs = JSON.parse(this.responseText);

             var output = '';

             for (var i in descrs) {
               output += '<ul>' +
                   '<li class="ajax_img_descr">ID: ' + descrs[i].img_descr + '</li>' +  '</ul>';
             }
             document.getElementById('descrs').innerHTML = output;
         }
       }
       xhr.send();
     }
    </script>
  </body>
</html>

UPDATE

Q1: Do I have to work with the "img_id" to achieve that or is there a other to do this? Do you want, that I start a new question for this?

Ans1: ID is something that should always be unique for all the elements. Via ID you can uniquely identify the Node in the DOM. You can use the img_id from DB which is primary key.

Q2: every description are getting displayed all together by clicking any button. What i need is: Click title 1 --> get descr 1, click title 2 --> get descr 2 and so on and so forth and the title list are getting loaded dynamically

Ans2: You can do this using this way, though there are multiple ways to do this:

// 1.1 PHP Change
while ($row = mysqli_fetch_array($result)) {
  // changed <button id='img_descr'> to <button class='img_descr' id=row's id column>
  echo "<div class='img_title'><button class='img_descr' id="$row['id']"><a>Title: <b>" . $row['img_title'] . "</b></a></button></div>";
}

// 1.2 JS change
function loadDescr(e) {
     ...
     console.log(e.target.innerHTML); // use console.log() very often in JS code!
     let id = e.target.getAttribute('id'); // get the ID of element, e.target.id also does the same 
     var xhr = new XMLHttpRequest();
     xhr.open('GET', 'ajax.php?img='+id, true); // append the id in query
     ...
 }

// 1.3 PHP ajax.php change

// check if the query has id passed
if (isset($_GET['img'])) {
    $id = $_GET['img'];
    // change the query to find by id
    $query = "SELECT * from images where img_id=$id";
} else {
    $query = "SELECT * from images";
}
$result = mysqli_query($conn, $query);
// Fetch Data
$users = mysqli_fetch_all($result, MYSQLI_ASSOC);
echo json_encode($users);

Hope this helps!

Related