Homepage

How to initialise jQuery Slick Carousel in a Turbolinks application

A guide to implementing jQuery Slick Carousel with Turbolinks and a fix for slick-carousel initialisation errors on turbolinks:load ‘revisit/back’ actions

The following example required the implementation of jQuery slick-carousel for a Ruby on Rails project running with Turbolinks. Turbolinks events have a couple of small unexpected quirks when trying to initialise slick-carousel and other jQuery libraries.

First we need to install our slick-carousel package; I’m going to use Node Package Manager for this example, but feel free to use whichever package manager you prefer:

npm i --save slick-carousel

Or add the package to your build via CDN - you can read more about slick-carousel here: https://www.npmjs.com/package/slick-carousel

Be sure to import or require the package in your main application.js (or wherever relevant in your build):

require("slick-carousel");

You can also import slick-carousel base styles:

import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";

For non-Turbolinks applications we would normally test whether a page has loaded with window.load, and then initialise slick-carousel on our elements. However we need a slightly different approach with Turbolinks; we need to listen for the turbolinks:load event:

document.addEventListener('turbolinks:load', function () {
  // Do this
});

In order to initialise slick-carousel we do the following; listen for the turbolinks:load event, target whichever element we want to slick and pass in our configuration object:

document.addEventListener('turbolinks:load', function () {
  $(‘.slick-me').slick({
    arrows: false,
    dots: false,
    autoplay: true,
    autoplaySpeed: 5000,
    touchThreshold: 500,
    speed: 300,
    waitForAnimate: false,
    responsive: [
      {
        breakpoint: 576,
        settings: {
          slidesToShow: 1,
          slidesToScroll: 1,
        }
      },
      {
        breakpoint: 992,
        settings: {
          slidesToShow: 2,
          slidesToScroll: 2,
        }
      },
      {
        breakpoint: 1200,
        settings: {
          slidesToShow: 3,
          slidesToScroll: 1,
        }
      }
    ]
  });
});

It’s as simple as that… sort of. The turbolinks:load event perhaps unexpectedly fires twice when navigating to a new page. Once before the new window has loaded and once after it has loaded.

This causes an issue with initialising slick-carousel on our DOM elements. If a user loads up a page for the first time slick-carousel will correctly initialise on turbolinks:load as it only fires once. However, if a user navigates away from the page with our slick-carousel and then revisits the page by hitting ‘back’ in the browser, slick-carousel will attempt to initialise before the selected element is loaded into the DOM. This may throw a console error in your browser along the lines of:

Uncaught TypeError: Cannot read property 'add' of null
  at Slick.initADA (slick.js:1208)
  at Slick.init (slick.js:1191)
  at new Slick (slick.js:179)
  at jQuery.fn.init.$.fn.slick (slick.js:2677)

The way around this is to explicitly unbind any slick-carousels on the page before the window has finished loading. We do this in turbolinks by creating another event listener:

document.addEventListener("turbolinks:before-cache", function () {
  const sliders = document.querySelectorAll('.slick-initialized');
 
  sliders.forEach(item => {
    $(item).slick('unslick');
  })
});

Now, Turbolinks will unbind slick-carousel elements when a user navigates between pages and correctly reinitialises after the window has finished loading.

What other people say

Other peoples’ opinions matter. I have worked with many people over the years and think it is important to share their experience of working with me.

  • React Development

    Tried and tested React application development. From super-fast single page applications to efficient large-scale corporate websites.

  • High-quality Templating

    Experienced approach to coding consistent and maintainable frontend templates and component libraries.

  • Accessibility Implementation

    Deep understanding of website accessibility, accessibility consultation, practical design, development, and testing experience.