Count total featured images inside an ACF repeater gallery?

Hi there, this is a fun one… :wink:

I want to count the number of featured media items inside an ACF repeater gallery so that I can choose to display the default images or just the featured ones. The images have a featured checkbox as pictured.

I was planning to count and set the number of featured items and then use the output with an <If...> statement to decide which images to display.

I know the below logic is incorrect and should not work, but it’s as close as I can get right now. The logic needs to check each gallery in the repeater and count how many images are ticked as featured.

<Get loop=count /> returns a total, but I can’t see what it’s actually counting.

<!--Set total featured image count-->
<Loop acf_repeater="sim_image_gallery_repeater">
    <Loop acf_gallery="sim_image_gallery">
        <If acf_checkbox="sim_media_options" any_is value="sim_featured_image">
            <Set local="featured_image_total">
                <Get loop=count />
            </Set>
        </If>
    </Loop>
</Loop>

The local variable featured_image_total will be used as below, and this works fine when the total is correct:

<If check="{Get local=featured_image_total}" more_than value="0">
    <!--Featured Gallery-->
    <Else />
    <!--Default Gallery-->
</If>

Maybe there is a simpler solution using <If loop exists...> but I could not get this work either, so perhaps I need to use some Math here?

Thanks.

Hi there, maybe you can try this if it will work on your end

<If loop acf_repeater="sim_image_gallery_repeater">
    <Loop acf_repeater="sim_image_gallery_repeater">
      <If loop acf_gallery="sim_image_gallery">
        <Loop acf_gallery="sim_image_gallery">
          <!--Featured Gallery-->
        </Loop>
        <Else />
        <!--Default Gallery-->
      </If>
    </Loop>
    <Else />
    <!--Default Gallery or some fallback you want-->
  </If>  

also,

<Get loop=count />

gets how many times the loop repeats which is the current loop count.

1 Like

I think the issue with that approach is that you’re checking whether a gallery loop exists, whereas what @Rips seems to need is something that checks whether there are any items within that loop that have a checkbox checked. Still, your idea of just displaying the different gallery types within the logic could work with some tweaking. The only thing is that when you write If loop exists, you then want to open that loop with a basic <Loop> according to the docs. If you redefine your query again in the loop tag, you’re effectively querying the data twice (once in the If tag and again in the Loop tag), if I’m not mistaken.

Are you able to work with the ACF checkbox field as if it were a normal field? I imagine this would depend on what’s contained in it but if that works, you could simplify your idea down to this:

<Loop acf_repeater=sim_image_gallery_repeater>
  <If loop exists acf_gallery=sim_image_gallery field=sim_media_options field_compare=any_is field_value=sim_featured_image>
    <Loop></Loop>
    <Get loop=previous_total />
  </If>
</Loop>

I think you’d need to open the inner loop with a Loop tag in order to be able to access the previous_total loop variable, but you could do some testing there to see if that’s necessary.

Thanks all, I think there is an issue with using <Get loop="total" /> and <Get loop=previous_total /> inside an ACF repeater. If these are not counting the loops accurately, it will prevent any solution from working.

I simplified things by switching sim_featured_image to an acf_true_false field, which works fine for creating a loop with only the featured images.

The below test returns 8 for both the loop_total and the previous_total, which is the total number of images in the second repeater gallery only, the count does not include the 3 images from the first repeater gallery. At least one of these totals should be 11.

@benjamin, there might be a bug here if you can check with a dev. I can work around this issue for now, it’s not a critical thing. :slight_smile:

<!--Set total featured image count-->
<Loop acf_repeater="sim_image_gallery_repeater">
    <Loop acf_gallery="sim_image_gallery">
        <If acf_true_false="sim_featured_image" is value="1">
            <Set local="loop_total">
                <Get loop="total" />
            </Set>
        </If>
    </Loop>
    <Set local="previous_loop_total">
        <Get loop=previous_total />
    </Set>
</Loop>

Loop Total: <Get local="loop_total" /><br>
Previous Loop Total: <Get local="previous_loop_total" />

It seems to be working correctly as far as I can see. Your <Get loop="total" /> is running within the loop and your <Get loop=previous_total /> is running after the loop. In both cases they’re displaying the total number of items from the same loop, so it makes sense that they’d be the same. Wrapping that first one in some conditional logic won’t affect what it’s counting (the total number of items in the loop), it only changes in what context that variable gets set. That’s why in my example I filtered the loop using attributes to only loop through the items I wanted to count. If you aren’t able to filter the loop, then you’ll need to use the Math tag to increment a variable by one each time your conditional logic runs. You’ll also need to use the Math tag if you want to add up multiple loop totals.

Edit: here’s an example of how this might work from another thread:

Thanks Ben, however, I may not have explained the issue properly.

I just did a couple of simple ACF repeater tests using <Get loop="total" /> to count the total number of items.

A repeater with a basic text field works fine and counts all rows:

<!--Set repeater text loop count-->
<Loop acf_repeater="repeater_test_2">
    <Set local="loop_total_2">
        <Get loop="total" />
    </Set>
</Loop>
<br>
Loop Total: <Get local="loop_total_2" />

A repeater with multiple galleries/images only counts the last gallery:

<!--Set repeater gallery loop count-->
<Loop acf_repeater="repeater_test">
    <Loop acf_gallery="gallery">
        <Set local="loop_total">
            <Get loop="total" />
        </Set>
    </Loop>
</Loop>
<br>
Loop Total: <Get local="loop_total" />

This is despite the fact the loop returns all images from all galleries (rows).

It looks like repeater galleries are unique in how they function compared to other fields because each gallery (row) can hold multiple images. A repeater checkbox may also have this issue, but I have not tested this.

Here is what a repeater gallery looks like for reference:

This still seems like L&L is working correctly unless I’m still misunderstanding. In the example you showed, you’ve got two galleries in your repeater. The way your template would work is that it would loop through the first gallery, set the variable equal to five, then loop through the second gallery, and set the same variable (overwriting it) to three. It’s only counting the last gallery because that’s the final thing that ends up getting saved into your variable when your template runs.

If you want to add up the loop totals from multiple galleries, you’re going to have to use the Math tag to add things up as shown in Julia’s post in the other thread that I linked to above.

Okay, but that’s not what I expect of <Get loop="total" /> because it’s a different number from what the loop actually outputs on the front end, maybe this could be improved so it’s more intuitive or a parameter added to modify its behaviour.

I will have a look at the Math option, I just try to avoid deploying scripts for small problems. :slight_smile:

But it’s not different. You’re not outputting eight gallery images here. Instead, you’re outputting five gallery images, then setting a variable to be equal to five (the current inner loop total the first time your outer loop runs), then the second time your loop runs, you’re outputting three images, then overwriting your variable to set it equal to three (the new current inner loop total the second time your outer loop runs).

I’d love to improve the docs but I don’t understand what’s unclear. A loop repeats its inner content once for each item in the loop. That means that, regardless of what kind of variable you’re working with, if you set a variable inside a loop, it will get set and reset as many times as the loop repeats. If you want to instead add up a series of values every time your loop runs (called incrementing in programming-speak) you need to account for that in how you build your template. I’m not sure where I’d put that in the docs because that’s just how variables work in math/programming in general and isn’t specific to L&L or to the loop total variable.

I’m open to suggestions though if you can think of where this might go. Maybe as an example associated with the Math tag.

Perhaps update this section in the docs to clarify that <Get loop="total" /> will not always output the same number of items as the loop itself due to it resetting on each loop.

But what I’m saying is that <Get loop="total" /> does always output the same number of items as the current loop. The only reason you’re running into an issue is because instead of displaying that value, you’re saving it to a variable and the variable is getting overwritten every time your outer loop runs because that’s how loops work.

Thanks, I see how it works now, however, I found a solution that does not require any counting of loops. :slight_smile:

The solution simply needs to display a different set of images if at least one image has been marked as featured. So, I don’t need to count anything just set a variable to ‘true’ if a featured image is found in the repeater/gallery loop.

Working solution:

  1. Loop through the galleries/images and set the variable:
<!--Check for featured images-->
<Loop acf_repeater="sim_image_gallery_repeater">
    <Loop acf_gallery="sim_image_gallery">
        <If acf_true_false="sim_featured_image" is value="1">
            <Set local="featured_image_true">true</Set>
        </If>
    </Loop>
</Loop>
  1. Display the default or featured gallery:
<!--Check gallery type-->
<If check="{Get local=featured_image_true}" is value="true">
    <!--Featured images gallery-->
    <div class="sim-gallery slick">
        <Loop acf_repeater="sim_image_gallery_repeater">
            <Loop acf_gallery="sim_image_gallery">
                <If acf_true_false="sim_featured_image" is value="1">
                    <Field image />
                    <Else />
                    <!--Not a featured image-->
                </If>
            </Loop>
        </Loop>
    </div>
    <Else />
    <!--Default images gallery-->
    <div class="sim-gallery slick">
        <Loop acf_repeater="sim_image_gallery_repeater">
            <Loop acf_gallery="sim_image_gallery">
                <Field image />
            </Loop>
        </Loop>
    </div>
</If>
2 Likes

Nice, that’s a smart approach!