->isNotEmpty() not working outside of foreach loop

I have the following code to render my block. Underneath the foreach-code, there is another piece of code, which should be displayed, if $image->caption()->isNotEmpty(). But the button inside is displayed as soon as only one captions of all images is not empty.

I think that is the case because it is not in the foreach loop, but for visual reasons, the button has to be outside of the div “content”…

What is missing here?

<div class="content">
<?php 
  $images = $block->images()->toFiles();
  foreach ($images as $image): ?>
  <div class="project" style="height: auto; background-image: url(<?= $resizeUrl ?>)">
    <div class="caption-and-counter" id="caption-and-counter">
      <h5 class="image-caption">
        <?= $image->caption() ?>
      </h5>
      <?php  if($images->count() > 1): ?>
        <h5 class="image-counter">
          <?php $total = $images->count(); ?>
          <?= $images->indexOf($image) + 1 . "&#8202;&#8202/&#8202&#8202;" . $total;?>
        </h5>
      <?php endif ?>
    </div>
  </div>
<?php endforeach ?> 
</div>  

  <?php  if($image->caption()->isNotEmpty()): ?>
  <button class="mobile-caption-toggle" id="mobile-caption-toggle">
    <h4 class="caption-plus visible" id="caption-plus">
      +
    </h4>
    <h4 class="caption-minus" id="caption-minus">
      –
    </h4>
  </button>
  <?php endif ?>

That doesn’t really make sense. $image is only defined inside the loop and you probably don’t want to show only one caption for all images?

Right, I want to display a caption of each image. The problem is indeed that it is not inside the loop. But how can I achieve that without putting it inside the loop? Creating another loop where I define $image again?

You can’t. There’s probably something wrong with your markup. Why should the buttons be outside the content div, when the images are inside the div?

Alright. It’s because of absolute positioned elements on top of it and I need to separate the divs because both are clickable…
But I just wanted to know if it is possible so I don’t have to change my html.
Thanks anyway!

Well, you can either have a content div for each element then put the caption below, or you need an extra loop for the captions.

What would the extra loop it look like? I already tried this:

  <?php 
    $images = $block->images()->toFiles();
    foreach ($images as $image): ?>
  <?php  if($image->caption()->isNotEmpty()): ?>
  <button class="mobile-caption-toggle" id="mobile-caption-toggle">
    <h4 class="caption-plus visible" id="caption-plus">
      +
    </h4>
    <h4 class="caption-minus" id="caption-minus">
      –
    </h4>
  </button>
  <?php endif ?>
<?php endforeach ?>  

Yes, that’s what I meant.

Maybe you can post the resulting HTML structure you want to have at the end.

The only problem here is that the code is visible when caption is empty. The images already display the correct caption as everthing is wrapped in another foreach loop of my collection:

<?php foreach ($munichPastPages as $exhibition): ?>
  // other code
<?php 
$files = $exhibition->content()->get('images')->toFiles();
foreach($files as $image): ?>
  // other code
<?php endforeach ?> 

<?php  if($image->caption()->isNotEmpty()): ?>   // <-- not working
<button class="mobile-caption-toggle" id="mobile-caption-toggle">
    <h4 class="caption-plus visible" id="caption-plus">
    +
    </h4>
    <h4 class="caption-minus" id="caption-minus">
    –
    </h4>
</button>
<?php endif ?>
<?php endforeach ?>

Therefore I think I don’t even need another foreach loop of all images, right?
But what could be the problem with ->isNotEmpty ?

Thanks!

In my opionion, this code doesn’t make sense. $image will always only refer to the last image in the $files loop, and if there are no files in a page, it will even be undefined and throw an error. In any case, I don’t believe you want only one caption for all the image, but one caption per image.

So the correct code would have to look like this:

<?php foreach ($munichPastPages as $exhibition): ?>
  <!--- some HTML -->
  <?php 
  $files = $exhibition->content()->get('images')->toFiles();
  foreach($files as $image): ?>
    <!-- other code -->
    <?php  if($image->caption()->isNotEmpty()): ?>   // <-- not working
    <button class="mobile-caption-toggle" id="mobile-caption-toggle">
        <h4 class="caption-plus visible" id="caption-plus">
        +
        </h4>
        <h4 class="caption-minus" id="caption-minus">
        –
        </h4>
    </button>
    <?php endif ?>
  <?php endforeach ?> 
<?php endforeach ?>

Thanks @texnixe, and what would it look like when I create another loop for it to work?
Due to the functionality of my html code it is not possible to put the button inside the first loop…

Like you posted above. But you didn’t answer my question from above, what you want the resulting HTML to look like.

Alright, but it does not work with the code I posted above…

What I have is a slider, but it is just an Image and when you click on it, you get the next Image out of the loop. Now, I want the button (code above) on the slider/image.
So in the end I have two clickable elements on top of each other and this is only working when I place the button code out of the slider div. Then, I place the button on top of the slider div with absolute positioning. Only then, the clickable elements are both working, the button is on top of the clickable slider and when the button is clicked, the slider underneath it is not clicked.

Otherwise, when both clickable elements are in one div, just the slider is triggered on click…

The slider looks like this:
("+" is the button-code on top of it)

-----------
|         |
|         |
|         |
| +       |
-----------

This image doesn’t answer my question, I asked for the HTML you want as result. Independent of PHP and the loops.

But I think you just need an additional container div

This is my HTML, i hope that’s helpful:

<div class="block-image-slider" id="block-image-slider">

    <div class="wrap">
        <div class="content">
            <div class="project_wrap no_select" id="test">
                <div class="project" style="background-image: url()">
                    <img src="data:image/png;base64,iVBORw" alt="Image" />
                    <div class="caption-and-counter" id="caption-and-counter">
                        <h5 class="image-caption">
                            Caption Text
                        </h5>
                        <h5 class="image-counter">
                            1/9
                        </h5>
                    </div>
                    <div>
                        <h5 class="mobile-image-counter">
                            1/9
                        </h5>
                    </div>
                </div>
            </div> <!-- project_wrap --> 
        </div> <!-- content --> 
    </div> <!-- wrap -->

    <button class="mobile-caption-toggle" id="mobile-caption-toggle">
        <h4 class="caption-plus visible" id="caption-plus">
        +
        </h4>
        <h4 class="caption-minus" id="caption-minus">
        –
        </h4>
    </button>
    
</div> <!-- block-image-slider -->

Sorry, that is not what I meant. What I wanted is the pure HTML structure (completely free of any PHP code) that you need to create a working slider with a button for each image. Because, obviously, the code you have doesn’t work as expected.

Sorry, I adjusted the code above! :slight_smile:

So only one button even if there are multiple images? I think I have to give up, I’m not getting it.

I only need one because it should be part of the foreach loop, then it will be shown for every single image and display a dynamic field like a caption… The only thing I want to achieve is that the button is hidden if no caption is given for the related image.

Then it must be inside the foreach loop. That’s why I was asking for a working HTML structure with multiple images and multiple buttons that works.