"Undefined is not an object" When trying to reference a cell in HTML

Viewed 341

I'm trying to make a table with data from the user on a website. I added the option to erase the row but I get an error

"undefined is not an object (evaluating 'table.rows[i].cells[3]')"

My code works if I use a fixed table, but with the script to make the table editable it doesn't work, here is my code:

<html>
    <head>

        <title>Remove HTML Table Selected Row</title>
        <meta charset="windows-1252">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
            td:last-child{background-color: #F00;color:#FFF;cursor: pointer;
                          font-weight: bold;text-decoration: underline}

        </style>

    </head>
    <body>

        <div class="container">
            <div class="tab tab-1">
                <table id="table" border="1">
                    <tr>        
                        <th>First Name</th>
                        <th>Last Name</th>
                        <th>Age</th>
                        <th>Delete</th>
                    </tr>
                    <tr>

                    </tr>

                </table>
            </div>
            <div class="tab tab-2">
                First Name :<input type="text" name="fname" id="fname">
                Last Name :<input type="text" name="lname" id="lname">
                Age :<input type="number" name="age" id="age">

                <button onclick="addHtmlTableRow();">Add</button>

            </div>
        </div>

        <script>

            var rIndex,
                table = document.getElementById("table");

            // check the empty input
            function checkEmptyInput()
            {
                var isEmpty = false,
                    fname = document.getElementById("fname").value,
                    lname = document.getElementById("lname").value,
                    age = document.getElementById("age").value;

                if(fname === ""){
                    alert("First Name Connot Be Empty");
                    isEmpty = true;
                }
                else if(lname === ""){
                    alert("Last Name Connot Be Empty");
                    isEmpty = true;
                }
                else if(age === ""){
                    alert("Age Connot Be Empty");
                    isEmpty = true;
                }
                return isEmpty;
            }

            // add Row
            function addHtmlTableRow()
            {
                // get the table by id
                // create a new row and cells
                // get value from input text
                // set the values into row cell's
                if(!checkEmptyInput()){
                var newRow = table.insertRow(table.length),
                    cell1 = newRow.insertCell(0),
                    cell2 = newRow.insertCell(1),
                    cell3 = newRow.insertCell(2),
                    cell4 = newRow.insertCell(3),
                    fname = document.getElementById("fname").value,
                    lname = document.getElementById("lname").value,
                    age = document.getElementById("age").value,
                    edit = "Edit"

                cell1.innerHTML = fname;
                cell2.innerHTML = lname;
                cell3.innerHTML = age;
                cell4.innerHTML = edit;
                // call the function to set the event to the new row
                selectedRowToInput();
            }
            }

            // display selected row data into input text
            function selectedRowToInput()
            {

                for(var i = 1; i < table.rows.length; i++)
                {
                    table.rows[i].onclick = function() 
                    {
                      // get the seected row index
                      rIndex = this.rowIndex;
                      document.getElementById("fname").value = this.cells[0].innerHTML;
                      document.getElementById("lname").value = this.cells[1].innerHTML;
                      document.getElementById("age").value = this.cells[2].innerHTML;
                    };
                }
            }
            selectedRowToInput();


            var index, table = document.getElementById('table');
            for(var i = 1; i < table.rows.length; i++)
            {
                table.rows[i].cells[3].onclick = function() //Line with the error
                {
                    var c = confirm("do you want to delete this row");
                    if(c === true)
                    {
                        index = this.parentElement.rowIndex;
                        table.deleteRow(index);
                    }

                    //console.log(index);
                };

            }



        </script>

    </body>
</html>

Any ideas what might the problem be?, Thanks a lot

3 Answers

Basically At the first iteration of the loop try to access third <td> (cell) which doesn't exist.

<table id="table" border="1">
                    <tr>        
                        <th>First Name</th>
                        <th>Last Name</th>
                        <th>Age</th>
                        <th>Delete</th>
                    </tr>
         
                    <tr>
                       <!-- there is no cell --> 
                    </tr>
                    
                </table>

Therefore undefined error shows up.

you can remove it as it has no use.

And

You should execute the loop after inserted some data into the table. Just wrap the loop in a condition. (if you remove the <tr> then our condition should be table.rows.length > 1)

    if(table.rows.length > 2){
           for(var i = 1; i < table.rows.length; i++)
                    {
                        table.rows[i].cells[3].onclick = function() 
                        {
                            var c = confirm("do you want to delete this row");
                            if(c === true)
                            {
                                index = this.parentElement.rowIndex;
                                table.deleteRow(index);
                            }
                            
                            //console.log(index);
                        };
                        
                    }
}
    

you don't need to loop inside function addHtmlTableRow() just add class to the Edit then setup event handler for dynamically added element using

document.addEventListener('click',function(e){
if(e.target){
      //do something
   }
});

var rIndex,
  table = document.getElementById("table");

// check the empty input
function checkEmptyInput() {
  var isEmpty = false,
    fname = document.getElementById("fname").value,
    lname = document.getElementById("lname").value,
    age = document.getElementById("age").value;

  if (fname === "") {
    alert("First Name Connot Be Empty");
    isEmpty = true;
  } else if (lname === "") {
    alert("Last Name Connot Be Empty");
    isEmpty = true;
  } else if (age === "") {
    alert("Age Connot Be Empty");
    isEmpty = true;
  }
  return isEmpty;
}

// add Row
function addHtmlTableRow() {
  // get the table by id
  // create a new row and cells
  // get value from input text
  // set the values into row cell's
  if (!checkEmptyInput()) {
    var newRow = table.insertRow(table.length),
      cell1 = newRow.insertCell(0),
      cell2 = newRow.insertCell(1),
      cell3 = newRow.insertCell(2),
      cell4 = newRow.insertCell(3),
      fname = document.getElementById("fname").value,
      lname = document.getElementById("lname").value,
      age = document.getElementById("age").value,
      edit = 'Edit';

    cell1.innerHTML = fname;
    cell2.innerHTML = lname;
    cell3.innerHTML = age;
    cell4.innerHTML = edit;
    cell4.className = "delete"; // <== add this class
    // call the function to set the event to the new row
    selectedRowToInput();
  }
}

// display selected row data into input text
function selectedRowToInput() {

  for (var i = 1; i < table.rows.length; i++) {
    table.rows[i].onclick = function() {
      // get the seected row index
      rIndex = this.rowIndex;
      document.getElementById("fname").value = this.cells[0].innerHTML;
      document.getElementById("lname").value = this.cells[1].innerHTML;
      document.getElementById("age").value = this.cells[2].innerHTML;
    };
  }
}
selectedRowToInput();

// for deleting row
document.addEventListener('click', function(e) {
  if (e.target && e.target.classList.contains('delete')) {
    if (confirm("do you want to delete this row")) {
      e.target.parentElement.remove();
    }
  }
});
td:last-child {
  background-color: #F00;
  color: #FFF;
  cursor: pointer;
  font-weight: bold;
  text-decoration: underline;
}
 <div class="container">
   <div class="tab tab-1">
     <table id="table" border="1">
       <tr>
         <th>First Name</th>
         <th>Last Name</th>
         <th>Age</th>
         <th>Delete</th>
       </tr>
       
       <tr>

       </tr>

     </table>
   </div>
   <div class="tab tab-2">
     First Name :<input type="text" name="fname" id="fname">
     Last Name :<input type="text" name="lname" id="lname">
     Age :<input type="number" name="age" id="age">

     <button onclick="addHtmlTableRow();">Add</button>

   </div>
 </div>

Arrays in Javascript starts at 0. In your example, this means that:

- rows[0] = Header row
- rows[1] = First data row
- rows[2] = Second data row

And so forth. Your for loop starts counting a 1.

Therefore, your for loop tries to access the second row in the table, but when the page first loads, this row doesn't contain any cells.

This is why the script says that undefined is not an object. The for loop will try to access row[1].cells[3] but row[1] doesn't have any cells. So, you're trying to access a cell that doesn't exist.

Related