Skip to main content

Choose theme:

blog of developer & bookworm benjamin read

Advanced Custom Fields and Bootstrap Tabs

I'm not a huge fan of Advanced Custom Fields, but there was a requirement to use it in a recent project that had Bootstrap as a basis for the UI. The challenge for me was to get Bootstrap nav-tabs to play nice with an ACF repeater field.

I started with the basic HTML markup for Bootstrap's Nav Tabs:

<ul class="nav nav-tabs">
<li role="presentation" class="active"><a href="tabone">TabOne</a></li>
<li role="presentation"><a href="tabtwo">TabTwo</a></li>
<li role="presentation"><a href="tabthree">TabThree</a></li>
<div class="tab-content">
<div class="tab-pane active" id="tabone">
Some content in tab one
<div class="tab-pane active" id="tabtwo">
Some content in tab two
<div class="tab-pane active" id="tabthree">
Some content in tab three

In the Field Groups settings, I created a Repeater (this is a paid-for add on to the standard Advanced Custom Fields) called "tab Panes", with 2 sub-fields, "Tab Title" and "Tab Contents".

<!-- Check for parent repeater row -->
<?php if( have_rows('tab_panes') ): ?>

<ul class="nav nav-tabs" role="tablist">
<?php // Step 1: Loop through rows, first displaying tab titles in a list
while( have_rows('tab_panes') ): the_row();

<li role="presentation" class="active">

<?php the_sub_field('tab_title'); ?>
<?php endwhile; // end of (have_rows('tab_panes') ):?>
<?php endif; // end of (have_rows('tab_panes') ): ?>

The PHP above displays the tabs. The code below, very similarly, displays the tab panes:

<?php if( have_rows('tab_panes') ): ?>
<div class="tab-content">
<?php// number rows ?>
<?php // Step 2: Loop through rows, now displaying tab contents
while( have_rows('tab_panes') ): the_row();
// Display each item as a list ?>

<div class="tab-pane active" id="tabone">
<?php the_sub_field('tab_contents'); ?>
<?php endwhile; // (have_rows('tab_panes') ):?>
<?php endif; // (have_rows('tab_panes') ): ?>

By looping through the same repeater, we can get all the tabs out of the database, no problem. But we still have two problems: 1) linking the tab to the pane 2) Assigning the class of "active" so the Javascript is able to add and remove the CSS to reveal / hide the appropriate pane.

###1) Linking to the Pane

There are a number of ways to do this. I could ask the user to input a number to uniquely identify the tab pane. But that would add extra work to the users flow, and they might easily find themselves out of their depth. I want to make this as easy as possible for the user.

On the other hand, Wordpress has a very useful function called Sanitize HTML, which we input the value of the title, take out spaces and capitals, and use this as the link:

<a href="#<?php echo sanitize_html_class( the_sub_field( 'tab_title' ) ); ?>"

###2) Assigning the 'Active' Class

So now we need to get a class of 'active' only on the first tab. The Bootstrap Javascript will do the rest for us. How do we do that?

I added this code just inside the while loop, inside the ul tag:

<?php $row = 1; // number rows ?>

This php is a counter. So we can identify the first instance and assign an if statement to it.

<a class="<?php if($row == 1) {echo 'active';}?>">

The final thing to do, is to keep the counter running, but adding this jsut before the endwhile.

<?php $row++; endwhile; // (have_rows('tab_panes') ):?>

Once you've added these to the tab panes in a similar way, you'll be up and running with Boostrap Tabs.

Below is a Github Gist, with the complete code for reference. Link to this (if you can't see the iFrame).