skip to Main Content

I am trying to use map function in my code, but I am afraid that I am making some silly mistakes. It just does not work!

Here is my code. I have 2 buttons captioned "ID" and "Text". Clicking them should show the list of IDs and texts of the input field. The program works fine until the map.

Can you Gurus help me understand my mistake?

<!DOCTYPE html>
<html>
    <head>
        <script>
            getID = (x) => x.id;
            getText = (x) => x.value;
            function Click(x) {
                input = document.getElementsByTagName("input");
                alert(input.map((x.id == "id") ? getID : getText));
            }
        </script>
    </head>
    <body>
        <input type="input" id="input1"> </input>
        <input type="input" id="input2"> </input>
        <button id="id" onclick="Click(this)"> ID </button>
        <button id="text" onclick="Click(this)"> Text </button>
    </body>
</html>

2

Answers


  1. The .map() method is part of the Array.prototype which allows you to use it on arrays, however, input in your case is not an array, it’s a HTMLCollection (as that’s what getElementsByTagName returns). You could convert the HTMLCollection to an array using the spread syntax const inputArray = [...input];, or using const inputArray = Array.from(input) and once converted perform your mapping with .map(), however, it would be more efficient to use the second argument of Array.from() to perform your mapping while converting (this avoids two iterations over your collection):

    const input = document.getElementsByTagName("input");
    alert(Array.from(input, (x.id == "id") ? getID : getText));
    

    On a side note, you should declare getID and getText with const or let to scope them to your current script and to avoid making them global. The same idea applies to input, declare this with const/let/var to keep it scoped to your function where it’s declared:

    const getID = (x) => x.id;
    const getText = (x) => x.value;
    
    function Click(x) {
      const input = document.getElementsByTagName("input");
      alert(Array.from(input, (x.id == "id") ? getID : getText));
    }
    <input type="input" id="input1"> </input>
    <input type="input" id="input2"> </input>
    <button id="id" onclick="Click(this)"> ID </button>
    <button id="text" onclick="Click(this)"> Text </button>
    Login or Signup to reply.
  2. The issue in your code is with how you’re trying to use the map function. getElementsByTagName returns an HTMLCollection, which is an array-like object, not an actual array. Therefore, you can’t directly use array methods like map on it.

    To fix this, you can convert the HTMLCollection into an array before using map. You can use Array.from or the spread operator … for this purpose.

    Here’s the corrected code:

    <!DOCTYPE html>
    <html>
    <head>
        <script>
            getID = (x) => x.id;
            getText = (x) => x.value;
    
            function Click(button) {
                input = document.getElementsByTagName("input");
                let inputsArray = Array.from(input); // Convert HTMLCollection to Array
                if (button.id === "id") {
                    alert(inputsArray.map(getID));
                } else if (button.id === "text") {
                    alert(inputsArray.map(getText));
                }
            }
        </script>
    </head>
    <body>
        <input type="input" id="input1"> </input>
        <input type="input" id="input2"> </input>
        <button id="id" onclick="Click(this)"> ID </button>
        <button id="text" onclick="Click(this)"> Text </button>
    </body>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search