How to add multiple Bootstrap 4 accordions using a Advanced Custom Fields repeaters

So this one stumped me for a little while.

I built a site for a client who wanted to use Advanced Custom Fields flexible content layouts to build content on a page. One of those layouts was an accordion, which was built using an ACF repeater. So far, all good.

However, the client needs to have multiple accordions on the same page, either for FAQ, team members with bios, anything. I’d built the flexible content layouts with the accordion pulling in data fine, but to do this you need break it down into 2 parts:

 

1. Creating a dynamic accordion using a repeater.

2. Adding this functionality into a flexible layout for possibility of having multiple accordion repeaters in multiple layouts.

 

Here’s how I did this:

1. Create a dynamic accordion using a repeater

This is different to just having hardcoded accordions as each accordion title and panel needs a UNIQUE ID. So Panel 1 title needs to open panel 1, panel title 2 opens panel 2 and so forth…

<?php if( have_rows('accordion_content') ) { $counter = 1; ?>
<div id="accordion" class="accordion-container my-3">
<?php while ( have_rows('accordion_content') ) { the_row(); $count = $counter++; ?>
<div class="card mb-2">
<div class="card-header accordion-title p-0" id="heading-<?php echo $count; ?>">
<h5 class="mb-0">
<button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapse-<?php echo $count; ?>" aria-expanded="false" aria-controls="collapse-<?php echo $count; ?>">
<?php echo get_sub_field('title'); ?>
</button>
</h5>
</div>
<div id="collapse-<?php echo $count; ?>" class="collapse accordion-content" aria-labelledby="heading-<?php echo $count; ?>" data-parent="#accordion-<?php echo $count; ?>">
<div class="card-body">
<?php echo get_sub_field('content'); ?>
</div>
</div>
</div>
<?php } ?>
</div>
<?php } ?>
</div>

This is achieved by adding a counter ( seen on the first line as $counter = 1;) and adding a count with every row.

This gives each repeater an incremental ID (seen at $count = $counter++;).  So $count becomes the value of the current repeater item whenever we call it.  For each repeater, this gives a unique value.  We then echo this to the accordion in both the title of the panel and its’ corresponding panel holding the collapsing panel.  e.g,

id="collapse-<?php echo $count; ?>"

 

This outputs in the front-end HTML:

id="collapse-1"
The problem with this is when we need to add multiple accordions.  As we run this counter with each repeater, it means that when we start a new repeater in a new accordion, the first will have the same count again.  This was seen when opening the accordion – it would open every 1st panel in all accordions, as the javascript was opening any panels with id=”collapse-1″ for example.

After a few moments and experiements, I discovered all that was needed was to add a separate counter on the Flexible Content fields themselves, so each row of the flexible content also had its own counter.  Then within each layout, we ran another counter on the accordion repeaters.

<?php if( have_rows('main_content') ) { $dfcounter = 1; ?>
<div class="main-text">
<?php
while ( have_rows('main_content') ) { the_row(); $dfcount = $dfcounter++;
if( get_row_layout() == 'text' ) {
echo get_sub_field('text');
} elseif( get_row_layout() == 'button' ) {
echo '<a class="btn btn-'.get_sub_field('button_colour').' btn-'.get_sub_field('button_size').'" href="'.get_sub_field('button_link').'">'.get_sub_field('button_text').'</a><br>';
} elseif( get_row_layout() == 'accordion' ) {
?>
<?php if( have_rows('accordion_content') ) { $counter = 1; ?>
<div id="accordion-<?php echo $dfcount; ?>" class="accordion-container my-3">
<?php while ( have_rows('accordion_content') ) { the_row(); $count = $counter++; ?>
<div class="card mb-2">
<div class="card-header accordion-title p-0" id="heading-<?php echo $dfcount; ?>-<?php echo $count; ?>">
<h5 class="mb-0">
<button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapse-<?php echo $dfcount; ?>-<?php echo $count; ?>" aria-expanded="false" aria-controls="collapse-<?php echo $dfcount; ?>-<?php echo $count; ?>">
<?php echo get_sub_field('title'); ?>
</button>
</h5>
</div>
<div id="collapse-<?php echo $dfcount; ?>-<?php echo $count; ?>" class="collapse accordion-content" aria-labelledby="heading-<?php echo $dfcount; ?>-<?php echo $count; ?>" data-parent="#accordion-<?php echo $dfcount; ?>">
<div class="card-body">
<?php echo get_sub_field('content'); ?>
</div>
</div>
</div>
<?php } ?>
</div>
<?php } ?>
<?php
} elseif( get_row_layout() == 'slideshow' ) {
include(locate_template('/partials/slideshow.php'));
} elseif( get_row_layout() == 'table' ) {
include(locate_template('/partials/table.php'));
} elseif( get_row_layout() == 'carousel' ) {
include(locate_template('/partials/carousel.php'));
} elseif( get_row_layout() == 'staff_profiles' ) {
//include(locate_template('/partials/staff.php'));
?>
Above, I have the first counter set as $dfcounter;  which counts the rows on the flexible content fields.  I then have the original counter on the accordion rows  ($count; ).

And then for the repeater accordions, you can see I set the ID in the accordion panels to use both the Flexlible content Count and the Accordion repeater row count together, so each repeater for accordions in each row of flexible content have completely unique IDs so panels are all separated and work exactly as they should.

 

Useful post? Share it

Leave a Reply

Your email address will not be published. Required fields are marked *