3

I have been racking my brain all morning about this. In my HTML code I have a list containing letters a - j and want to console log the letter when it is clicked.

I have created a for loop to run through the nodelist and I can get the script to console log out the number of the element that is being clicked but as soon as I try and get the innerHTML or anything like that it returns undefined.

But when I just type el[3].innerHTML for example into the console it returns the letter I want.

Please help me understand why just because it's going through a for loop does it make it undefined?

I'm not just looking for the solution but also to learn why it's happening so I can become a better coder.

Thanks!

Code:

var list = document.getElementsByTagName('ul')[0];
var el = list.getElementsByTagName('li');

for(var i = 0; i < el.length; i++ ) {
  el[i].addEventListener('click', function(f) {
    return function(event) {
      event.preventDefault();
      console.log(f.innerHTML);
    }
  }(i));
}
4
  • Is the script on the top of the page before the li has been written to the page? Note also letters are not elements of an element, you should only see a test node string, if there are no other elements. Commented Aug 25, 2017 at 11:21
  • Is possible that f is not defined inside the function, can you put also the html or a plunker example to make a quick test? Commented Aug 25, 2017 at 11:21
  • Possible duplicate of How to get radio button value after onclick event in prototype Commented Aug 25, 2017 at 11:28
  • f === i and i is an integer, which doesn't have the said property. Commented Aug 25, 2017 at 11:31

4 Answers 4

1

You miss name of variable at :

console.log(this.innerHTML);

var list = document.getElementsByTagName('ul')[0];
var el = list.getElementsByTagName('li');

console.log(el)

  for(var i = 0; i < el.length; i++ ) {
  el[i].addEventListener("click",function(f){

    return function(event){
        event.preventDefault();
        console.log(this.innerHTML);
    };
  }(i));
}
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>

Sign up to request clarification or add additional context in comments.

1 Comment

which makes the entire IIFE unnecessary.
1

When you pass i as your argument into the function, f takes on the value of i so when you try to get f.innerHTML you're attempting to get the HTML from an integer, rather than from the element that was clicked.

You can use this to target the element that was clicked. Here is a working example:

var list = document.getElementsByTagName('ul')[0];
var el = list.getElementsByTagName('li');

  for(var i = 0; i < el.length; i++ ) {
  el[i].addEventListener("click",function(f){

    return function(event){
        event.preventDefault();
        console.log(this.innerHTML);
    };
  }(i));
}
<ul>List
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
</ul>

Edited with corrected information thanks to @Teemu.

Comments

0

Here is working example, I think it was problem with passing correct element

var list = document.getElementsByTagName('ul')[0];
   var el = list.getElementsByTagName('li');

   for(var i = 0; i < el.length; i++ ) {
   el[i].addEventListener("click",function(e){

     return function(event){
      event.preventDefault();
      console.log(e.innerHTML);
   };
 }(el[i]));
}

Comments

0

Your Main Problem

As alredy mentiont in the comments by @teemu your f is the event object. And to access innerHtml you need to access target befor.

Idea

Currently you have n <li> elements an eventListener. You can have only one on your <ul> to have a cleaner code base.

Code

When you add the eventListener to <ul> you can access each clicked element in it via event.target.

var list = document.getElementsByTagName('ul')[0];

list.addEventListener('click', logInnerHtml)

function logInnerHtml(event) {
    event.preventDefault()
    console.log(
        event.currentTarget.innerHtml
    )
}

Example

var list = document.getElementsByTagName('ul')[0];

list.addEventListener('click', logInnerHtml)

function logInnerHtml(event) {
  console.log(event.target.innerHTML)
}
<ul>
  <li>first</li>
  <li>second</li>
</ul>

1 Comment

Umh ... The event object was an incorrect statement from me, there's a new, more correct comment, has been there for almost an hour by now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.