skip to Main Content

I am studying html, css, and js.

Add click events to the arrow buttons of flickity,

I used addEventListener. However, I got the following error.

TypeError: Cannot read properties of null (reading 'addEventListener')
    at index.js:3:6

I’m still a beginner so I don’t know where I’m going wrong.


html

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://unpkg.com/flickity@2/dist/flickity.min.css">
</head>
<body>
    <h1>My Calendar</h1>

    <div class="header">
        <div class="carousel" data-flickity='{ "pageDots": false }'>
            <div class="carousel-cell">1</div>
            <div class="carousel-cell">3</div>
            <div class="carousel-cell">4</div>
            <div class="carousel-cell">5</div>
        </div>
    </div>

    <div class="container">
        
    </div>
    <script src="https://unpkg.com/flickity@2/dist/flickity.pkgd.min.js"></script>
    <script src="index.js"></script>
</body>

css

.carousel-cell {
    width: 100%;
    font-size: 48px;
    background: transparent;
    text-align: center;
}


.carousel .flickity-prev-next-button {
    width: 100px;
    height: 50px;
    background: transparent;
    border-radius: 0;
    border: none;
    box-shadow: none;
  }

 .carousel .flickity-prev-next-button.previous {
    left: 250px;
}

.carousel .flickity-prev-next-button.next {
    right: 250px;    
}

javascript

const btn = document.querySelector(".carousel .flickity-prev-next-button");


btn.addEventListener("click", () => {
    console.log("Hello")
});

2

Answers


  1. Your JavaScript is likely executed before Flickity elements have been added to the DOM. Flickity takes a bit of time to initialize, and the .flickity-prev-next-button elements might not yet exist when your code runs. This is indicated by the error message, as your selector returns a null object (i.e. nothing found).

    Consider using Flickity’s "ready" event to execute code after those dynamic elements are added to the DOM.

    ready
    Triggered after Flickity has been activated.

    Also, querySelector selects only the "first Element within the document that matches the specified selector," but there are two button elements. I used querySelectorAll to select both buttons and iterated through them using forEach to add event listeners.

    Also see Flickity complete event when initialized with HTML, although that example uses the "active" event rather than "ready".

    Flickity.prototype.on('ready', function() {
    
      const btns = document.querySelectorAll(".carousel .flickity-prev-next-button");
    
      btns.forEach(function(btn) {
        btn.addEventListener("click", () => {
          console.log("Clicked");
        });
      });
    
      console.log('Loaded');
    
    });
    .carousel-cell {
      width: 100%;
      font-size: 48px;
      background: transparent;
      text-align: center;
    }
    
    .carousel .flickity-prev-next-button {
      width: 100px;
      height: 50px;
      background: transparent;
      border-radius: 0;
      border: none;
      box-shadow: none;
    }
    
    .carousel .flickity-prev-next-button.previous {
      left: 250px;
    }
    
    .carousel .flickity-prev-next-button.next {
      right: 250px;
    }
    <script src="https://unpkg.com/flickity@2/dist/flickity.pkgd.min.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/flickity@2/dist/flickity.min.css">
    
    <h1>My Calendar</h1>
    
    <div class="header">
      <div class="carousel" data-flickity='{ "pageDots": false }'>
        <div class="carousel-cell">1</div>
        <div class="carousel-cell">3</div>
        <div class="carousel-cell">4</div>
        <div class="carousel-cell">5</div>
      </div>
    </div>
    
    <div class="container">
    
    </div>

    Alternatively, you could bind the event listener to a more static element (one that is not added later). See Adding an event listener to an element that doesn’t exist yet in vanilla javascript and the example below:

    // the carousel element exists prior to Flickity initialization, so no need to wait.
    const carousel = document.querySelector(".carousel");
    
    carousel.addEventListener("click", (event) => {
      let element = event.target;
      // is the clicked element part of a prev/next button?
      if (element.closest(".flickity-prev-next-button")) {
        console.log("Clicked");
      }
    });
    .carousel-cell {
      width: 100%;
      font-size: 48px;
      background: transparent;
      text-align: center;
    }
    
    .carousel .flickity-prev-next-button {
      width: 100px;
      height: 50px;
      background: transparent;
      border-radius: 0;
      border: none;
      box-shadow: none;
    }
    
    .carousel .flickity-prev-next-button.previous {
      left: 250px;
    }
    
    .carousel .flickity-prev-next-button.next {
      right: 250px;
    }
    <script src="https://unpkg.com/flickity@2/dist/flickity.pkgd.min.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/flickity@2/dist/flickity.min.css">
    
    <h1>My Calendar</h1>
    
    <div class="header">
      <div class="carousel" data-flickity='{ "pageDots": false }'>
        <div class="carousel-cell">1</div>
        <div class="carousel-cell">3</div>
        <div class="carousel-cell">4</div>
        <div class="carousel-cell">5</div>
      </div>
    </div>
    
    <div class="container">
    
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search