Home > front end >  I want to change the style in a item with a button click in the item, but when i click the button on
I want to change the style in a item with a button click in the item, but when i click the button on

Time:09-30

I called an api from a website to make a list of items in my own website.

I do that with foreach. The list gets imported correctly, but I have a little problem.

Each item in the list has an description with display: none; and each item also has a button. If I click that button I want to make the display: inline;

I tried a lot of things, but every time I click a button only the first item in the foreach list changes.

I am not really good at explaining, but hopefully someone can help me.

        <?php
        foreach ($items as $item):
            echo "<script> 
            
            function hide_post(){
                hideshow = document.querySelector('#showMoreLessId');
                hideshowtext = document.querySelector('#showMoreLess');
                if (hideshow.style.display == 'inline'){
                    hideshow.style.display = 'none';
                    hideshowtext.innerHTML = 'Toon meer';
                }else{
                    hideshow.style.display = 'inline';
                    hideshowtext.innerHTML = 'Toon minder';
                }
            }
            </script>";
        ?>
            <div  id="item">
                <h4>Versie: <?= $item->name;  ?></h4>
                <div id="showMoreLessId">
                    <p>Issues in versie: <?= $res->issuesFixedCount; ?> </p>
                    <p>Afgeronde issues: <?= $roundedIssue;?> </p>
                    <p>Nog te verwerken issues: <?= $uns->issuesUnresolvedCount;?> </p>
                </div>
                <small><?= $item->releaseDate; ?></small>
                <a onclick="hide_post()" id="showMoreLess">Toon meer</a>
                <a>|</a>
                <a href="<?='version/?version=' . $item->name; ?>">Meer info</a>
            </div>
            <?php
        endforeach;?>
    </div>
</div>

CodePudding user response:

The reason is that document.querySelector('#showMoreLessId'); will only get the first one

I would suggest you to assign a unique identifer to each element(using _<?= $item->name; ?> for example)

<?php
        foreach ($items as $item):
            echo "<script> 
            
            function hide_post(){
                hideshow = document.querySelector('#showMoreLessId_'<?= $item->name;  ?>);
                hideshowtext = document.querySelector('#showMoreLess_'<?= $item->name;  ?>);
                if (hideshow.style.display == 'inline'){
                    hideshow.style.display = 'none';
                    hideshowtext.innerHTML = 'Toon meer';
                }else{
                    hideshow.style.display = 'inline';
                    hideshowtext.innerHTML = 'Toon minder';
                }
            }
            </script>";
        ?>
            <div  id="item">
                <h4>Versie: <?= $item->name;  ?></h4>
                <div id="showMoreLessId_<?= $item->name;  ?>">
                    <p>Issues in versie: <?= $res->issuesFixedCount; ?> </p>
                    <p>Afgeronde issues: <?= $roundedIssue;?> </p>
                    <p>Nog te verwerken issues: <?= $uns->issuesUnresolvedCount;?> </p>
                </div>
                <small><?= $item->releaseDate; ?></small>
                <a onclick="hide_post()" id="showMoreLess_"<?= $item->name;  ?>>Toon meer</a>
                <a>|</a>
                <a href="<?='version/?version=' . $item->name; ?>">Meer info</a>
            </div>
            <?php
        endforeach;?>
    </div>
</div>

CodePudding user response:

Your issue is because you're repeating the same id on multiple elements in the DOM as you loop to create the HTML.

To fix this issue apply class attributes to the repeated content instead, and then use document.querySelectorAll() to retrieve them. Note that you will need to loop through the returned collection as well.

In addition you will need to use DOM traversal to find the elements related to the clicked a element.

In addition, your JS function should only be declared once, outside of your PHP loop.

Here's a working example with the above changes applied. Note that I also changed the class names to better describe the purpose of the elements.

// JS logic only defined once, separate from your PHP code...  

document.querySelectorAll('.toggle').forEach(el => {
  el.addEventListener('click', hide_post);
});

function hide_post(e) {
  e.preventDefault();
  
  const toggle = e.target;
  const item = e.target.closest('.item');
  const details = item.querySelector('.details');
  
  if (details.style.display == 'inline') {
    details.style.display = 'none';
    toggle.innerHTML = 'Toon meer';
  } else {
    details.style.display = 'inline';
    toggle.innerHTML = 'Toon minder';
  }
}
.details { display: none; }
<!-- HTML content generated by your PHP loop... -->

<div >
  <h4>Versie: $item->name1</h4>
  <div >
    <p>Issues in versie: $res->issuesFixedCount1</p>
    <p>Afgeronde issues: $roundedIssue1</p>
    <p>Nog te verwerken issues: $uns->issuesUnresolvedCount1</p>
  </div>
  <small>$item->releaseDate1</small>
  <a href="#" >Toon meer</a>
  <a>|</a>
  <a href="<?='version/?version=' . $item->name; ?>">Meer info</a>
</div>

<div >
  <h4>Versie: $item->name2</h4>
  <div >
    <p>Issues in versie: $res->issuesFixedCount2</p>
    <p>Afgeronde issues: $roundedIssue2</p>
    <p>Nog te verwerken issues: $uns->issuesUnresolvedCount2</p>
  </div>
  <small>$item->releaseDate2</small>
  <a href="#" >Toon meer</a>
  <a>|</a>
  <a href="<?='version/?version=' . $item->name; ?>">Meer info</a>
</div>

  • Related