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")
});
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>