Adding a jQuery Slider to a Magento 2 Site

This is the second in my series of JavaScript in Magento 2. To follow along, I have created a GitHub repo with the starter theme on the master branch and a branch for each article at their finished point. This post will include content for the theme and for cms content. To follow along, checkout to the master branch and add the code as you go. If you get stuck, you can always checkout to the branch for this article for the final code.

I’m going to make the assumption that you have a working Magento 2 install loaded with the default sample data running a child theme using the Luma theme as its parent. Of course this information will work across any setup you have, but if you are following along you will want this set up.

And since I’m using I will be using Mark Shust’s Docker environment, the root of my site will include a src for my files paths. If you are using another development env, just omit that.

Perennial Requests

In the last article we set up a blank cms page, added some JavaScript with Require JS and did a simple animation of some content on the page. We will use that as the starting point for what we are going to do today. Not a week goes by without a client asking for a slider on their site. There is a healthy debate if sliders are even effective on a website. But that debate aside, if they are going to requests it we should all figure out how to do it correctly. This is going to be a step by step process of setting up a slider, with breaks along the way to talk about the “why” of what we are doing. I’m going to move in a backward direction explaining how to set up your files correctly. The idea being it’s best to know why a config file needs to be set up when you know what you are configuring. The first thing we need to do is jump into a cms page of our dev site in the admin (Content -> Pages -> edit the page we worked on last article). Inside the page replace the content with the code below. I’m reusing the same image that is in the default Luma theme, but feel free to use any images you like.

<div class="blocks-promo" id="custom-top-slider">
 <div>
  <a class="block-promo home-main" href="{{store url=""}}collections/yoga-new.html">
   <img src="{{media url="wysiwyg/home/home-main.jpg"}}" alt="" />
   <span class="content bg-white">
    <span class="info">New Luma Yoga Collection</span>
    <strong class="title">Get fit and look fab in new seasonal styles</strong>
    <span class="action more button">Shop New Yoga</span> 
   </span>
  </a>
 </div>
 <div>
  <a class="block-promo home-main" href="{{store url=""}}collections/yoga-new.html">
   <img src="{{media url="wysiwyg/home/home-main.jpg"}}" alt="" />
   <span class="content bg-white">
    <span class="info">New Luma Yoga Collection</span>
    <strong class="title">Get fit and look fab in new seasonal styles</strong>
    <span class="action more button">Shop New Yoga</span> 
   </span>
  </a>
 </div>
 <div>
  <a class="block-promo home-main" href="{{store url=""}}collections/yoga-new.html">
   <img src="{{media url="wysiwyg/home/home-main.jpg"}}" alt="" />
   <span class="content bg-white">
    <span class="info">New Luma Yoga Collection</span>
    <strong class="title">Get fit and look fab in new seasonal styles</strong>
    <span class="action more button">Shop New Yoga</span> 
   </span>
  </a>
 </div>
</div>

<script type="text/x-magento-init">
{
  "*": {
    "Magento_Theme/js/custom-slider": {}
  }
}
</script>

The code here is straight forward, the only thing to note is the use of the script tag to “call” our JavaScript. You will notice that we are using a “type” that is custom to Magento 2 – type="text/x-magento-init. We will cover this in greater depth down the road, but for now just know that this is telling Magento that we are going to be using its built-in JavaScript rending system. Magento will read this and then look to the file we are pointing to in the active theme (Magento_Theme/js/custom-slider.js) and if it finds it, it will render that file onto this page. The * in the script is a jQuery like selector of a DOM element on the page. It could be the targeted HTML element (in our case the blocks-promo class or the homepage-top-slider id) and you will see that a lot in core code.

In a future blog post I will go over this configuration in detail and all the ways we can use it. Before we keep going, it’s important to understand what this code is actually doing. I explained the syntax, but conceptually this line of code is equivalent to linking to a script file with <script type="text/javascript" src="src/app/design/frontend/LearningJsTheme/theme/Magento_Theme/web/js/custom-slider.js"></script>. There is sometimes confustion about how to “get” a JavaScript file onto a page in Magento 2, this is exactly how that is done. With that in place, lets save the page and then move to our theme and create the aforementioned JavaScript file (src/app/design/frontend/LearnJs/theme/Magento_Theme/web/js/custom-slider.js).

Notice that the file path and the call to the file path are different. It’s a convention in the Magento 2 JavaScript system to leave out parts of the path that is taken for granted (something I feel is a hindrance to learning and de-bugging this system) and so the “web” is left out as well as the “.js”. Inside that file, we will have the call to the slider and its parameters.

// File: src/app/design/frontend/LearnJs/theme/Magento_Theme/web/js/custom-slider.js

define([
    'jquery',
    'slick'
], function ($) {
    'use strict';

    $('#custom-top-slider').slick({
        adaptiveHeight: true,
        autoplay: true,
        autoplaySpeed: 2000,
        arrows: false,
        infinite: true,
        slidesToShow: 1,
        slidesToScroll: 1,
    });
});

Here we have a good distillation of what a JavaScript file in Magento 2 looks will need in the file we are using. We have jquery and that is being passed into the anonymous function as $. Then we have the Slick slider itself. That doesn’t require us to pass it in with the anonymous function though as it only needs to be initialized on the page. That makes the global slick available for us to use in the way we have all grown accustom to using it. The settings inside the .slick({}) are yours to play around with, these are just some common defaults. With the JavaScript files ready to go, the next step is to grab the slider’s files and to “register” them with Require JS so it knows where to find them and load them. As mentioned above, we are using the Slick slider. Truth be, you can use any slider you like, but this one has always work well for me. The placement of the download files have a little wiggle room but per convention, I will be placing them here:

src/app/design/frontend/LearnJs/theme/Magento_Theme/web/js/vendor/slick.min.js
src/app/design/frontend/LearnJs/theme/Magento_Theme/web/css/vendor/slick-theme.css
src/app/design/frontend/LearnJs/theme/Magento_Theme/web/css/vendor/slick.css

With those in place we can create our requirejs-config.js file. For each theme (or module) you only need one configuration file living in your root. This file will manage all our custom scripts, vendor files, mixins and shims (more on that in a future blog post). Right now we just have the simple registration of the Slick slider so that it can now be used site wide.

// File: src/app/design/frontend/LearnJs/theme/requirejs-config.js

var config = {
    map: {
        '*': {
            slick: 'Magento_Theme/js/vendor/slick.min'
        }
    }
};

You can think of this file as the brain of your JavaScript nervous system. It’s job is to know where everything that you customize is and what role it’s going to play. In this case we are using the map object to “register” the Slick slider file. So, you might be thinking “well, we didn’t have to put the custom-slider.js here, so if this is the brain, why do we have files outside it’s view”. To extend the metaphor to it’s limits, even though the brain is in control, there are still systems that are mostly independent. If you just need to pull a file into a page, and that is the only place you will be using that file, and you are not going to be using that file as a dependency of any other, then it’s simple enough to just call that file directly. Since there is a chance we might want to use a slider on many different places on a site, we register it here. We now need to load the CSS styles into the site, and we will do that by simply calling it in the head of the site with some xml (src/app/design/frontend/LearnJs/theme/Magento_Theme/layout/default.xml).

//File: src/app/design/frontend/LearnJs/theme/Magento_Theme/layout/default.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <css src="Magento_Theme::css/vendor/slick.css" />
        <css src="Magento_Theme::css/vendor/slick-theme.css" />
    </head>
</page>

There are a lot of ways to use css in Magento 2, and we don’t have time to cover them all. There is an included LESS file with Slick that can be used with Magento 2’s build in LESS compiler, but for simplicity we will just load CSS styles in the head. After adding these new files, we are going to have to recompile (so the files can be copied over to the pub/static folder), so run the php bin/magento setup:static-content:deploy -f from the root of your site and after it’s done clear the cache for good measure with php bin/magento cache:clean. When you refresh your page, you should now have a fully working slider.

Closing Thoughts

The way JavaScript is implemented in Magento 2, while it may take you a little while to get used to, is leaps and bounds ahead of Magento 1. Require JS brings order and organization, not to mention ease of use, when it comes to JavaScript and Magento. It opens up the ability to pull in libraries and code reliably without resorting to hacks or “pray as you go” development techniques. While this system has some hurdles to overcome, one of the most consistent request from clients can be solved in a modular way in just a few files. In the next post we are going to dive even deeper into Require JS in Magento 2 and how to debug problems when “it just isn’t loading” become the mantra of the work day.

Hope to see you there.