Home > Net >  TypeError: Cannot read properties of "undefined"
TypeError: Cannot read properties of "undefined"

Time:10-01

I was practicing my array manipulation with a simple dynamic selector using HTML, CSS, and JavaScript when I came across something peculiar. My JS functions seem to be behaving as I want them to, but I get a console error whenever they run. It reads

   Uncaught TypeError: Cannot read properties of undefined (reading 'name')

Could someone take a look at my code and see what is happening? Like I said, everything seems to be acting as I would expect, I just cannot figure out why it is throwing this console error, especially because it is clearing reading the object correctly.

let selector = document.querySelector(".selector");

let options = [];

let createItem = (input) => {
  let item = {};
  item.name = input;
  item.id = Math.trunc(Math.random() * 50);
  options.push(item);

  let el = document.createElement("option");
  el.setAttribute("value", input);
  el.setAttribute("id", item.id);
  el.innerHTML = input;
  selector.appendChild(el);
};

createItem("Apple");
createItem("Pear");
createItem("Grape");
createItem("Watermelon");

let addItem = (input) => {
  options.push(input);
  let latestOption = options[options.length - 1];
  createOptions(latestOption);
};

let deleteItem = (input) => {
  for (i = 0; i <= options.length; i  ) {
    let indexedItem = options[i].name;
    if (indexedItem === input) {
      let el = document.getElementById(options[i].id);
      el.remove();
      options.splice(i, 1);
    }
  }
};

let editItem = () => {
  for (i = 0; i <= options.length; i  ) {
    options[i].name = input;
    el = document.getElementById(i);
    el.setAttribute("value", input);
    el.innerHTML = input;
  }
};

document.querySelector(".add-btn").addEventListener("click", () => {
  let userInput = prompt("What should the new item be called?");
  createItem(userInput);
});

document.querySelector(".delete-btn").addEventListener("click", () => {
  let userInput = prompt("Which item would you like to delete?");
  deleteItem(userInput);
});

document.querySelector(".edit-btn").addEventListener("click", () => {
  let selectedItem = prompt("What item would you like to edit?");
  let newItemName = prompt("What would you like to rename it as?");
  for (i = 0; i <= options.length; i  ) {
    if (options[i].name === selectedItem) {
      options[i].name = newItemName;
      let el = document.getElementById(options[i].id);
      el.setAttribute("value", options[i].name);
      el.innerHTML = options[i].name;
    }
  }
});
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Options</title>
  </head>
  <body>
    <select title="selector" name="selector"  id=""></select>
    <button onClick="return false" >Add Item</button>
    <button onClick="return false" >Delete Item</button>
    <button onClick="return false" >Edit Item</button>
    <script src="script.js" defer></script>
  </body>
</html>

CodePudding user response:

The problem I see is with the way you defined the for loop in your function editItem.

Short answer:

replace for (i = 0; i <= options.length; i ) with for (i = 0; i < options.length; i ) (removing the = in the condition).

Long answer:

As to why its wrong, lets say options has 6 items in it, your for starts at i = 0 and is supposed to go on until i = 6, the problem is there is no options[6] (meaning it has 7 items if you include options[0]) so it cannot read property name of the non existent options[6].

As to why your code doesnt break, it actually does, the function stops working after that, which in your case doesnt cause a problem since the part it was executing was extra anyways.

CodePudding user response:

The issue was you did not use var i in your loop and also your <= should be <

for (var i = 0; i < options.length; i  ) {
          console.log(i);
          if (options[i].name === selectedItem) {
            options[i].name = newItemName;
            let el = document.getElementById(options[i].id);
            el.setAttribute("value", options[i].name);
            el.innerHTML = options[i].name;
          }
        }

full code

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Options</title>
  </head>
  <body>
    <select title="selector" name="selector"  id=""></select>
    <button onClick="return false" >Add Item</button>
    <button onClick="return false" >Delete Item</button>
    <button onClick="return false" >Edit Item</button>
    <script>
      let selector = document.querySelector(".selector");

      let options = [];

      let createItem = (input) => {
        let item = {};
        item.name = input;
        item.id = Math.trunc(Math.random() * 50);
        options.push(item);

        let el = document.createElement("option");
        el.setAttribute("value", input);
        el.setAttribute("id", item.id);
        el.innerHTML = input;
        selector.appendChild(el);
      };

      createItem("Apple");
      createItem("Pear");
      createItem("Grape");
      createItem("Watermelon");

      let addItem = (input) => {
        options.push(input);
        let latestOption = options[options.length - 1];
        createOptions(latestOption);
      };

      let deleteItem = (input) => {
        for (i = 0; i <= options.length; i  ) {
          let indexedItem = options[i].name;
          if (indexedItem === input) {
            let el = document.getElementById(options[i].id);
            el.remove();
            options.splice(i, 1);
          }
        }
      };

      let editItem = () => {
        for (i = 0; i <= options.length; i  ) {
          options[i].name = input;
          el = document.getElementById(i);
          el.setAttribute("value", input);
          el.innerHTML = input;
        }
      };

      document.querySelector(".add-btn").addEventListener("click", () => {
        let userInput = prompt("What should the new item be called?");
        createItem(userInput);
      });

      document.querySelector(".delete-btn").addEventListener("click", () => {
        let userInput = prompt("Which item would you like to delete?");
        deleteItem(userInput);
      });

      document.querySelector(".edit-btn").addEventListener("click", () => {
        let selectedItem = prompt("What item would you like to edit?");
        let newItemName = prompt("What would you like to rename it as?");
        console.log(options);
        for (var i = 0; i < options.length; i  ) {
          console.log(i);
          if (options[i].name === selectedItem) {
            options[i].name = newItemName;
            let el = document.getElementById(options[i].id);
            el.setAttribute("value", options[i].name);
            el.innerHTML = options[i].name;
          }
        }
      });
    </script>
  </body>
</html>

  • Related