Skip to main content

The Cheeky Monkey Media Blog

A few words from the apes, monkeys, and various primates that make up the Cheeky Monkey Super Squad.

Bootstrap Carousel + Drupal Paragraphs = Magic by Calvin Tyndall, Hybrid Monkey Wrencher at Cheeky Monkey Media

Bootstrap Carousel + Drupal Paragraphs = Magic

NOTE: This tutorial assumes you have some knowledge of Drupal site building, field and field display management. It will include some theming code examples.

If you've never heard of the Paragraphs module, it allows you to create "bundles" of fields and then call in those bundles via a paragraphs field on another entity. You can then add any number of these bundles into the entity, in any combination, to build out a page or some other super snazzy component.

Build bundles for a masthead, a pull quote, a banner, a simple text area... etc., and an editor now has a collection of tools to build dynamic pages, beyond the oldschool Title/Body/WYSIWYG situation. There are even modules that will help you get all parallaxy and animated with paragraphs.

The really beautiful thing is, you can nest paragraphs items. Yes, paragraphs items, within paragraphs items within... (The word Inception popped up a lot as we worked out various models).

Ok, so here's a practical example I built recently.

Part 1 - The Tools

Make sure you install the paragraphs module and a bootstrap based theme. You could use any theme and any carousel javascript library to do this, but bootstrap has carousel.js built in, and well, if you're not using Bootstrap, or Foundation based themes, you don't know what you're missing.

What I'm about to describe below for Bootstrap's Carousel will work exactly the same way with Foundation's Orbit. The only difference being slight changes in the markup and class names.

Part 2 - Fields and Entities

Create a paragraph bundle called "Slide". This will hold the fields for the content you consider one complete slide. It may be as simple as just an image field. You may want to include a text field and style the bundle to overlay the text with an image as the background. Whatever you want to see parading by on the screen.

The bundle you created is just an entity, so you can template and style this bundle any way you wish. It doesn't matter to the carousel. You may wish to use this slide component outside of the slideshow, maybe as a banner or something else. The magic comes with the next component.

Create a paragraph bundle called "Slide Container". As the name implies, this will hold the slides and do the work. You could call this "Carousel", or anything else, but I find it useful to include the word "container" as it will always be used to contain other paragraph bundles and it's useless alone. This naming convention extends to any other type of container bundle I make for other purposes.

The only field you really need on the next bundle is a Paragraphs field. Configure this field in the following way:

Make sure the widget type for the paragraphs field is "Embedded".

Label: Slides
Required: TRUE
Bundle: Check the slide bundle you created previously.
Item Title: Slide
Plural Item Title: Slides
Default View Mode: Preview *
Add Mode: Select List **
Number of values: 5 ***

* Using Preview as default view mode will render the bundle on the edit screen the same way it's rendered on the view screen. It will be contained inside a collapsed and draggable container, but will give you a good idea of how it's going to look once it's saved.

** You could choose Button for the Add Mode. With only one bundle available on this field it's going to render a button anyway, but if you have a whole bunch of bundles available on one paragraphs field using a select list keeps the UI less cluttered. This is important as things can get pretty complex with a lot of bundles flying around.

*** It's good to set limits on something like a carousel. Too many slides to load can have a negative impact on load times, etc. There are lots of reasons one might advise against ever using a carousel; this is just one. A google search on the topic may convince you to never use a carousel again... Oh well... maybe there's still something to be learned here.

On the Manage Display tab for this bundle, set the Slices field label to "Hidden" and the format to "Paragraphs Item".

Let's add one more field to this bundle for a little more control. Let's call it "Slide Interval". It's an "Integer" field type and "Text Field" widget. This will allow us to control how long the slides wait before changing.

I set a default value to 5000 and a suffix to "ms" for milliseconds. So the default slide interval will be 5 seconds.

On the Display settings for this field, just hide the field.

You'll notice on the Display Settings tab there is a sub tab for the "Paragraphs Editor Preview", view mode. (Remember when we set the default view mode to "Preview" earlier?) You can use this to set up how your fields are previewed. I usually match the default for field visibility.

One more thing to do and then on to some code!

We need to attach a Paragraphs field to a content type or some other entity we want to add slide shows to. For this tutorial just use a page content type or something. You can call this field Paragraphs, or Bundles, or Components, or whatever you want to think of these embedded bundles as.

Set the field settings as we did for the previous paragraphs field, changing titles and labels where appropriate. This time, you'll see 2 bundles in the bundles list. Just check the "Slide Container" bundle for now.

That's about it. You can create a page, then add a "Slide Container" to it. INSIDE the Slide Container, you'll see a button to "Add Slide". When you click that you'll get whatever fields you defined for the slide bundle. Add your image or other content there. Click the Collapse button on the Slide (not on the Slide Container), and the Slide bundle will collapse to preview mode.

Click "Add Slide" again, and repeat if you want, but I suggest at least 2 slides for this to demo well.

Now for the secret sauce...

Part 3 - Theming the Carousel

If you saved yourself some content with a couple of Slides inside a Slide Container, you may be a bit sad to see that it's not much to look at. It's kind of just sitting there stiffly like me at my first Jr. High dance when a girl asked me to get up and bust a move. Not very impressive - at - all...

Like many theming tasks we need 3 things: a hook_theme, a hook_preprocess and a tpl.php

Let's start with the preprocess actually, so we can set up a couple of variables for the tpl.

I usually use a feature module to hold all the config for the bundles and fields described above. But this code can go in a custom module, or even your theme. I'll prefix things with MY_THEME in the examples below.

  1. /**
  2.  * Implements hook_preprocess_entity().
  3.  */
  4. function MY_THEME_preprocess_entity(&$variables) {
  5.   // Only act on paragraphs_item entity types of the slide_container bundle.
  6.   if ($variables['entity_type'] == 'paragraphs_item' && $variables['paragraphs_item']->bundle === 'slide_container') {
  7.     // Start active_class TRUE for the first slide.
  8.     $variables['active_class'] = TRUE;
  9.     // For setting the slide interval.
  10.     $interval = field_get_items('paragraphs_item', $variables['paragraphs_item'], 'field_slide_interval');
  11.     $variables['interval'] = !empty($interval) $interval[0]['value'] :5000;
  12.   }
  13. }

The 'active_class' variable will be set to FALSE in the tpl after the first slide is rendered.

Now we need hook_theme() to register our tpl.php file for these entities.

  1. /**
  2.  * Implements hook_theme().
  3.  */
  4. function MY_THEME_theme($existing, $type, $theme, $path) {
  5.   return array(
  6.     'paragraphs_item__slide_container' => array(
  7.       'render element' => 'elements',
  8.       'path' => $path . '/templates',
  9.       'template'  => 'paragraphs-item--slide_container',
  10.     )
  11.   );
  12. }

And now we package it all up with our tpl file which we’ll put in a /templates directory inside our theme (as defined in the hook_theme() function above): paragraphs-item--slide_container.tpl.php

The markup in here comes from the Bootstrap examples found here:

I've only inserted php to set some attributes and add our slide content found in field_slides, attached to this paragraph bundle. As I mentioned, this markup could just as easily be the Orbit markup from Foundation, or anything else for the js plugin of your choice.

  1. <div id="carousel-component-<?php print $id; ?>" class="carousel slide" data-ride="carousel" data-interval="<?php print $interval; ?>">
  2.   <!-- Indicators -->
  3.   <ol class="carousel-indicators">
  4.     <?php foreach (element_children($variables['elements']['field_slides']) as $key) : ?>
  5.       <li data-target="#carousel-component-<?php print $id; ?>" data-slide-to="<?php print $key; ?>" <?php if ($active_class) { print 'class="active"'; } ?>></li>
  6.     <?php endforeach; ?>
  7.   </ol>
  8.   <!-- Wrapper for slides -->
  9.   <div class="carousel-inner" role="listbox">
  10.     <?php foreach (element_children($variables['elements']['field_slides']) as $key) : ?>
  11.       <div class="item <?php if ($active_class) { print 'active'; $active_class = FALSE; } ?>">
  12.         <?php print render($elements['field_slides'][$key]); ?>
  13.       </div>
  14.     <?php endforeach; ?>
  15.   </div>
  16.   <!-- Controls -->
  17.   <a class="left carousel-control" href="#carousel-component-<?php print $id; ?>" role="button" data-slide="prev">
  18.     <span class="fa fa-chevron-left" aria-hidden="true"></span>
  19.     <span class="sr-only">Previous</span>
  20.   </a>
  21.   <a class="right carousel-control" href="#carousel-component-<?php print $id; ?>" role="button" data-slide="next">
  22.     <span class="fa fa-chevron-right" aria-hidden="true"></span>
  23.     <span class="sr-only">Next</span>
  24.   </a>
  25. </div>

As you can see we loop through all the field_slides elements first to set up the slide indicator list items, second to render each slide into the slide wrapper. Notice $active_class is set to FALSE after the first slide is given the active class. The active class tells carousel.js which slide is in view.

That's It!

Once all this is in place you should clear caches and reload your page. You should see your slides cycle through! You may need some more style tweaks, but this is all it takes to get a modular slider in Drupal with Bootstrap and Paragraphs.

Just think about how easy it is to manage this content. Create a page, add a Slide Container, add a Slide, repeat. It's very intuitive and easily managed. Think about how you could expand on it with different slides. Make a Video Slide, Testimonial Slide and more, all available in the one Slide Container, just by adding more bundles!


If the slider ain't slidin', make sure carousel.js is being included in your theme.

Web Development

Would you like to know more about what we do?

View Our Services

Graphic Design Cheeky Monkey

Have a look at some our client work

View Our Work

Cheeky Monkey Discovery

Learn more about Cheeky Monkey Media

About Us