'Block disappears if there is no image in it

All health and happiness! A written script that should iterate through all the pictures, if the pictures did not load, then the script should hide the parent block under the .Parent_block class, that is, I have 3 blocks, there is a picture in the central block, but not in the other two, which means they should have property display:none

But I did something wrong. Where did I make a mistake?

let parent_block = document.querySelectorAll('.Parent_block');
let image_b = document.querySelectorAll('.Child_Img');

image_b.forEach(function(){

if(image_b.onerror){

for(let parent_block of hide){
hide.style.display = 'none';    
}

}

})
.Parent_block{
width:30%;
margin:0;
padding:0;
margin-left:10px;
margin-top:10px;
border:1px solid black;
display:inline-block;
height:250px;
}

img{
height:inherit;
width:100%;
<figure class="Parent_block"> <!-- ***** this block should disappear *****  =( -->
 
<img class="Child_Img" src="">

<figcaption class ="Img_text">1</figcaption> 

</figure>


<figure class="Parent_block"> 
 
<img class="Child_Img" src="https://i.ibb.co/kyXhZmB/photo-2021-11-18-14-40-18.jpg">

<figcaption class ="Img_text">2</figcaption> 

</figure>


<figure class="Parent_block"> <!-- ***** and this one too *****  =( -->
 
<img class="Child_Img" src="">

<figcaption class ="Img_text">3</figcaption> 

</figure>


Solution 1:[1]

There are some issues with the script.

  • You are running image_b.forEach and inside that you are trying to access image_b.onerror. This will not work since image_b is an array.
  • onerror is an event and not a property. So it cannot be accessed like this.
  • The syntax for(let parent_block of hide) is wrong.

Fixed Code

Logic

  • Select all elements with class name Child_Img.
  • Loop through the elements and register onerror event on each element in the list that we selected with class name Child_Img.
  • On the error event, find the closest element with class name Parent_block and hide it.

Working Fiddle

let image_b = document.querySelectorAll('.Child_Img');
image_b.forEach(function (img) {
    img.onerror = function(image) {
        img.closest(".Parent_block").style.display = 'none';
    }
})
.Parent_block {
    width: 30%;
    margin: 0;
    padding: 0;
    margin-left: 10px;
    margin-top: 10px;
    border: 1px solid black;
    display: inline-block;
    height: 250px;
}

img {
    height: inherit;
    width: 100%;
}
<figure class="Parent_block">
    <!-- ***** this block should disappear *****  =( -->

    <img class="Child_Img" src="">

    <figcaption class="Img_text">1</figcaption>

</figure>


<figure class="Parent_block">

    <img class="Child_Img" src="https://i.ibb.co/kyXhZmB/photo-2021-11-18-14-40-18.jpg">

    <figcaption class="Img_text">2</figcaption>

</figure>


<figure class="Parent_block">
    <!-- ***** and this one too *****  =( -->

    <img class="Child_Img" src="">

    <figcaption class="Img_text">3</figcaption>

</figure>

Solution 2:[2]

let parent_block = document.querySelectorAll('.Parent_block');
let image_b = document.querySelectorAll('.Child_Img');

image_b.forEach(function(image){
   // check if any error (if image doesn't load in our case)
   image.addEventListener("error",()=>{
      // find closest class name and hide it
      image.closest(".Parent_block").style.display = "none";
   })
})
.Parent_block{
width:30%;
margin:0;
padding:0;
margin-left:10px;
margin-top:10px;
border:1px solid black;
display:inline-block;
height:250px;
}

img{
height:inherit;
width:100%;
<figure class="Parent_block"> <!-- ***** this block should disappear *****  =( -->
 
<img class="Child_Img" src="">

<figcaption class ="Img_text">1</figcaption> 

</figure>


<figure class="Parent_block"> 
 
<img class="Child_Img" src="https://i.ibb.co/kyXhZmB/photo-2021-11-18-14-40-18.jpg">

<figcaption class ="Img_text">2</figcaption> 

</figure>


<figure class="Parent_block"> <!-- ***** and this one too *****  =( -->
 
<img class="Child_Img" src="">

<figcaption class ="Img_text">3</figcaption> 

</figure>

Solution 3:[3]

A very minimal solution could be done in the HTML. Remove all of your JS, and just change the <img> tags like so:

<img class="Child_Img" src="" onerror="this.parentElement.style.display = 'none';">

Solution 4:[4]

There are a number of problems with your script.
Some examples:

  1. onerror should not be checked with if, but with event listener.
  2. forEach needs an argument, you haven't provided any.
  3. You should add .onerror to the argument of foreach, and not directly to image_b
  4. There is no variable declared as hide in your script. I am guessing you intended for (let hide of parent_block)
  5. Assuming you fixed everything up to #4, the loop runs hide.style.display = 'none' for everything of parent_block, and not just the ones that includes the images with errors.

The following should work:

let parent_block = document.querySelectorAll('.Parent_block');
let image_b = document.querySelectorAll('.Child_Img');

image_b.forEach(function (cur_image) { 
    cur_image.onerror = function () {
        for(let block of parent_block){
            if(block.contains(cur_image) ){
                block.style.display = 'none';
            }
        }
    } 
}) 

But the loop over the parent_block is not necessary, you can just find the relevant ancestor of the cur_image:

// let parent_block = document.querySelectorAll('.Parent_block');
let image_b = document.querySelectorAll('.Child_Img');

image_b.forEach(function (cur_image) { 
    cur_image.onerror = function () {
        let hide = cur_image.closest('.Parent_block')
        hide.style.display = 'none';
    } 
}) 

Note that it's not even to required to run document.querySelectorAll('.Parent_block') anymore.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nitheesh
Solution 2 Codenewbie
Solution 3 Nicolas Goosen
Solution 4