Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community!
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial

Kristian Woods
23,414 PointsHow do you change images based off a click?
I'm trying to create a image gallery, that changes depending on which button/link you click. However, I can only seem to get the "image 1" gallery to show. "Image 2" and "image 3" don't appear at all.
I'm trying to achieve - when you click on one gallery, the other images that were there previously would disappear. I only want one gallery to display at a time. However, my "deleteImages" function doesn't seem to working, either.
I continue to get the error whenever I click "image 2" - Uncaught TypeError: Cannot read property 'length' of undefined
let link = document.querySelectorAll('a');
let imageContainer = document.querySelector('.image-container');
let images = document.querySelector('.image-container img');
let localPath;
let imageURL;
let imagesName = [
{
"album1": ["pexels-photo-412537.jpeg", "pexels-photo-748898.jpeg", "pexels-photo-1313191.jpeg"]
},
{
"album2": ["pexels-photo-426893.jpeg", "pexels-photo-573241.jpeg", "pexels-photo-1139370.jpeg"]
},
{
"album3": ["pexels-photo-58625.jpeg", "pexels-photo-1308684.jpeg", "pexels-photo-1308754.jpeg"]
}
];
function deleteImages() {
if(imageContainer.childElementCount > 0) {
images.forEach((img) => {
imageContainer.removeChild(img);
});
}
}
function createImg(src) {
let img = document.createElement("img");
img.src = src;
imageContainer.appendChild(img);
}
link.forEach((link) => {
link.addEventListener('click', (e) => {
e.preventDefault();
switch(link.textContent) {
case "image 1":
deleteImages();
localPath = "/images/album1/";
for (let i = 0; i < imagesName.length; i++) {
imageURL = imagesName[i].album1;
for (let n = 0; n < imageURL.length; n++) {
createImg(localPath + imageURL[n]);
}
}
break;
case "image 2":
deleteImages();
localPath = "/images/album2/";
for (let i = 0; i < imagesName.length; i++) {
imageURL = imagesName[i].album2;
for (let n = 0; n < imageURL.length; n++) {
createImg(localPath + imageURL[n]);
}
}
break;
case "image 3":
deleteImages();
localPath = "/images/album3/";
for (let i = 0; i < imagesName.length; i++) {
imageURL = imagesName[i].album3;
for (let n = 0; n < imageURL.length; n++) {
createImg(localPath + imageURL[n]);
}
}
break;
}
});
});
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<style>
.image-container {
width: 100%;
height: auto;
}
img {
max-height: 333px;
overflow: hidden;
}
</style>
</head>
<body>
<a href="#">image 1</a>
<a href="#">image 2</a>
<a href="#">image 3</a>
<div class="image-container">
</div>
<script src="js.js"></script>
</body>
</html>
1 Answer

Steven Parker
225,730 PointsAt first glance, I noticed that "deleteImages" relies on "images", which is being set at the beginning of the program, before any images are added. And "querySelectorAll" returns a static NodeList and not a live HTMLCollection, so it will remain empty even after images are added.
Kristian Woods
23,414 PointsKristian Woods
23,414 PointsHey, Steven - I found this solution worked:
I basically changed how I looped through the array. At first, I had an array that had 3 objects that contained an array within. So, I changed that to one object, that contains the 3 albums.
Steven Parker
225,730 PointsSteven Parker
225,730 PointsAnd moving where "images" is assigned fixed the empty list issue. Good deal.
Kristian Woods — You can mark the question solved by choosing a "best answer".
And happy coding!