Why JS doesn't find the element?

Good day!

Uncaught TypeError: Cannot set property 'innerHTML' of null
at HTMLInputElement.

I can not understand why JS doesn't find the label....

was perekupil even the English version, but there is no answer...

The task is to output the name of the uploaded file instead of the current record in the label tag.

Code below:

<label for="file" class="upload-label"><span>Upload</span></label>
<input type="file" name="file" id="file" class="hide inputfile" accept="application/vnd.ms-excel" 
data-multiple-caption="{count} selected files" multiple/>


var inputs = document.querySelectorAll( '.inputfile' );
Array.prototype.forEach.call( inputs, function( input )
{
 var label = input.nextElementSibling,
 labelVal = label.innerHTML;

 input.addEventListener( 'change', function( e )
{
 var fileName = ";
 if( this.files && this.files.length > 1 )
 fileName = ( this.getAttribute( 'data-multiple-caption' ) || " ).replace( '{count}', this.files.length );
else
 fileName = e.target.value.split( '\\' ).pop();

 if( fileName )
 label.querySelector( 'span' ).innerHTML = fileName;
else
 label.innerHTML = labelVal;
});
});


.hide {
position: absolute;
 overflow: hidden;
 z-index: -1;
 width: 0.1 px;
 height: 0.1 px;
 opacity: 0;
}

.upload-label{
 display: inline-block;
 cursor: pointer;
 background-color: #357;
 padding: 5px 80px;
 color: white;
 border-radius: 5px;
 border: 1px solid black;
}
April 4th 20 at 00:59
2 answers
April 4th 20 at 01:01
Solution
You are in school English was fair deuce, or bribed for triples? Well, that is - open a dictionary and see how to translate the word "next". Then see in what order your items are located.
I certainly understand that You would like to see the questions from Elon musk, but unfortunately I am one of those who learns )

Not really because again all just?
Swap input and label?

For that now the computer will not include )) - Keanu.Paucek91 commented on April 4th 20 at 01:04
@Keanu.Paucek91,

Swap input and label?

Or googling how to get the previous element. - Chris.Ritchie25 commented on April 4th 20 at 01:07
April 4th 20 at 01:03
Solution
About the problem with the next/previous already written, but the relative elements in General is fraught with problems, what will you do if tomorrow the layout will change?
label for input is better to look like this:
getLabelForInput function(input) {
 if(input.id) {
 const label = document.querySelector(`label[for="${input.id}"]`);
 if(label) { return label; }
}
 for(let parent = input; parent = parent.parentElement;) {
 if(parent.tagName === 'LABEL') { return parent; }
}
 return null;
}
Dmitry, here you wrote now instead of continue to go will with your example to understand)) - Keanu.Paucek91 commented on April 4th 20 at 01:06
@Keanu.Paucek91, a label can be associated with input in two ways:
1. using the for attribute that contains the id of the desired input
2. through nesting (nested input in label)

If the input has no id, the first case does not make sense, but if he is, then you can try to find the label using the selector attribute. If found - the problem is solved, so return.
In the loop, we pass up the DOM tree from our input, if the parents have a label - it and return, but if it came to the root of the DOM tree (the expression parent.parentElement will return null which is coerced to false), then it is logical to assume that the label associated with our input just yet. - amara_Pagac27 commented on April 4th 20 at 01:09
@amara_Pagac27, by far the best, thank you so much! - Keanu.Paucek91 commented on April 4th 20 at 01:12
@amara_Pagac27still will bother You:)

made input nested inside a label, but the name is not substituted...

where wrong?

<label for="file" class="upload-label">
 <input type="file" name="file" id="file" class="hide inputfile" accept="application/vnd.ms-excel" data-multiple-caption="{count} selected files" multiple/>to Upload</label>
- Keanu.Paucek91 commented on April 4th 20 at 01:15
@Keanu.Paucek91, to see how things have changed JS, one html is there not to understand - amara_Pagac27 commented on April 4th 20 at 01:18
@amara_Pagac27,

has not changed at all:
but after Your message I realized that it is necessary in the value of the function to put the id of impute, right?

getLabelForInput function(input) {
 if(input.id) {
 const label = document.querySelector(`label[for="${input.id}"]`);
 if(label) { return label; }
}
 for(let parent = input; parent = parent.parentElement;) {
 if(parent.tagName === 'LABEL') { return parent; }
}
 return null;
}
- Keanu.Paucek91 commented on April 4th 20 at 01:21
@Keanu.Paucek91, no, this function is passed the input itself - amara_Pagac27 commented on April 4th 20 at 01:24
@amara_Pagac27,

to change the function in the Array.prototype.forEach.call( ", ___?___ )?

then there is no need to var inputs = document.querySelectorAll( '.inputfile' ); - Keanu.Paucek91 commented on April 4th 20 at 01:27
@Keanu.Paucek91, here is a substitute: var label = getLabelForInput(input) - amara_Pagac27 commented on April 4th 20 at 01:30

Find more questions by tags JavaScript