1

Background Info:

I tried to create a custom theme for my carousel section and I am unable to get it to work. I have tried using the default carousel that Drupal comes with. I have tried using slide show views. Also I already know about Jim Bir's Custom Bootstrap Carousel and Slick Carousel but I am unable to use them since these extensions are still in Beta.

Problem Statement:

The main avenue that I want to try to do is create a paragraph type called Carousel Section that has a reference to another paragraph type called `Caraousel Slide'.

I wanted to use this design so that way I can organize the slides individually on my pages.

Within the Carousel Slide paragraph type it would have the following fields:

  1. Slide Image
  2. Slide Title
  3. Slide Description
  4. Slide Link(which is the location of where the slide will take you if you click on it.)

I would like to use a preprocessor hook do get grab these values from Drupal and display them in my twigg file.

Question:

How can I achieve my problem statement? The bare minimal knowledge that I need is to how to at least get these fields to present themselves on my twig file and from there I can use HTML and CSS to make the carousel.

  • I will reward the bounty to anyone that can walk me through how to implement this as well. – B. Cratty Nov 8 '18 at 15:07
8
+50

Unless you need some very specific logic, I wouldn't use preprocessing, but use Drupal's template suggestions and Twig instead.

I always use Slick over CDN, adjust for your own needs if necessary. All filenames are relative to the base directory of your theme or module. Replace UPPERCASE_WORDS with corresponding machine names.


Create a library for your carousel:

MYTHEME.libaries.yml

carousel:
  version: 1.0.0
  js:
    https://cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.js: {type: external, minified: true, defer: true, async: true}
    js/my_carousel.js: {}
  css:
    layout:
      https://cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick-theme.min.css: {type: external, minified: true}
      css/my_carousel.css: {}

js/my_carousel.js

behaviors are the drupalesque counterpart to jQuery's .ready() handler (e.g. even if your carousel is loaded inside a view with ajaxified paging, it will still trigger .slick() after every paging).

(function ($, Drupal) {
  Drupal.behaviors.myCarousel = {
    attach: function (context, settings) {
      $('[data-slick]', context).once('myCarousel').slick();
    }
  };
}(jQuery, Drupal));

templates/paragraph--CAROUSELCONTAINER.twig.html

The container template would be the place where you alter your slick options, e.g. if you have a integer field "Autoplay speed" on your container paragraph, you could add to my_carousel_options using paragraph.field_autoplay_speed.0.value

{% set my_carousel_options = '"autoplay": true' %}
{{ attach_library('MYTHEME/carousel') }}

<div{{attributes}} data-slick="{{ my_carousel_options }}">
  {{ content.FIELD_CONTAINING_SLIDES }}
</div>

templates/paragraph--CAROUSELSLIDE.twig.html

Here you can decide what to render on each individual slide

{# maybe you also need an additional wrapper <div> around each invidiual slide #}
<a href="{{ paragraph.MY_LINK_FIELD.0.url }}">
  {{ content.MY_IMAGE_FIELD }}
  {{ content.MY_TITLE_FIELD }}
  {{ content.MY_DESCRIPTION_FIELD }}
</a>

If necessary you can further adjust the HTML markup of your slide subfields using something like templates/field--paragraph--MY-DESCRIPTION-FIELD.html.twig


Optional:
If you want to get rid of some container <div>s around fields automatically rendered by Drupal, create a wrapper-less field template. E.g. I wanted to remove ALL <div>s and field labels rendered by any paragraph host field:
(this is global for every paragraph host field, change it to a template suggestion matching only your carousel if you don't want this)

field--entity-reference-revisions.html.twig

{% for item in items %}
  {{ item.content }}
{% endfor %}

Finally create your own CSS styles for your carousel in css/my_carousel.css and rebuild the cache so Drupal discovers your new template files.

This basically is how I'm creating carousels on every of my projects. Not tested with Bootstrap theme though, this is some sort of general purpose tutorial.

  • First I truly want to thank you for answering this question. This knowledge really doe help me understand the process better. This is very beneficial. There is one catch though....How hard would it be to use this for something else that other than Slick or Blazy? I bring this up because I don't know if I can use this because when I look at the Requirements for Slick Carousel there is mention that you need Blazy but when you scroll to the bottom of the page it says it still in development aka not green. – B. Cratty Nov 8 '18 at 16:41
  • The JS carousel is quite easy to replace: basically switch the library files, and change the JS carousel init call js/my_carousel.js (the line with the .slick). Regarding Blazy (or generally lazy loading images): This will be harder. You will need to alter the image field templates to provide the markup needed by Blazy. A module like Twig tweak will help you to render multiple or specific image styles. – Hudri Nov 8 '18 at 17:01
  • 2
    I personally prefer <img srcset> or <picture> and provide multiple image sizes. I intially render the gallery with something like .gallery .slide {display: block} .gallery .slide + .slide (display: none). After DOM ready the slider library will do the rest of the job. This works in at least as many browsers as Blazy and is much more bullet proof than any lazy loader. Using this technique I also get 90+ on Google Pagespeed insights on very design heavy sites (example) – Hudri Nov 8 '18 at 17:09
  • 1
    This answer would 100% be my approach. One paragraph as the slider which uses a paragraph reference field to add another paragraph type of slider-item. slider-item would hold all your content fields. Though you may want to trade out the paragraph reference for a node reference depending on if you want these slides to be reusable. Use Slick Slider all the way!!! kenwheeler.github.io/slick and control the markup in your twig files. – Prestosaurus Nov 9 '18 at 20:28
2

The Bootstrap Paragraphs module might be your best bet, as a quick and dirty drop-in solution. You say you're using Bootstrap and Paragraphs, and I believe that module might include nearly exactly what you're looking for:

  • a "Carousel" paragraph type,
  • containing a paragraphs reference field called "Slide Content" that
  • references another paragraph type called "Image".

If you'd rather use your own paragraph types, then perhaps the paragraph--bp-carousel.html.twig Twig file contained in that module could be useful for you to copy / paste some implementation details regarding the Bootstrap carousel settings.

For what it's worth, I've implemented a simplified carousel in my IU Paragraphs module, which also uses nested paragraph types, like Bootstrap Paragraphs, just with quite a bit less code in the Twig templates, that might be a cleaner start for you to look at:

  • The outer Twig template paragraph--iu-carousel.html.twig renders the wrapper div for the carousel.
  • The inner Twig template paragraph--iu-image.html.twig renders the <img> tags themselves, and optionally wraps them in a <figure> and <figcaption> tags if a caption is provided.
  • The carousel javascript is a custom implementation to load Slick slider based on a custom class (rotator), however that javascript to load the carousel is provided by Indiana University's web framework (http://assets.iu.edu/web/3.x/js/iu-framework.js), so that part of it may not be much help to you, but the Twig and HTML are clean and should get you started.

Anyway, I hope this might help as reinforcement of the general steps outlined above in Hurdi's answer. Good luck!

1

Since you've organized your data fairly well into paragraphs and paragraphs have standard class names for use with CSS and JS (depending on the theme you're using), a very easy solution will be to include a slider library (I use Slick) and write a behavior in your theme's JS file to initialize the slideshow.

  • Include the module which provides the slider - I'll assume it is Slick for the answer
  • Include the slick libraries in your theme: slick/slick.
    • Alternatively, you can write some PHP to include the slick/slick as an attachment to your carousel paragraph type with something like hook_preprocess_paragraph() or some other hook.
  • Write a behavior like Drupal.behaviors.custom_carousel = { ... }. And for every paragraph--type-carousel initialize a carousel with the parameters you want.

I've done this with many JS libraries, especially when they don't have a nice integration with Drupal.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.