【问题标题】:Problems with HTML and Javascript dynamic tableHTML和Javascript动态表的问题
【发布时间】:2021-05-18 23:11:08
【问题描述】:

我在以下方面遇到问题:

  1. 函数saveRow 不保存行。我收到此错误:

未捕获的类型错误:无法在 HTMLInputElement.onclick 的 saveRow 处设置未定义的属性名称。 2)deleteRow 不起作用。我收到类似的错误: 未捕获的类型错误:无法将属性“innerHTML”设置为空。 3) 在editRow 中,I 字段变为可编辑,但使用之前保存的默认值。例如,列表总是 A、B、C,这不是我想要的。我希望列表的初始值是之前选择的值。

我应该做错了什么。代码如下:

HTML:

<html>

<head>
</head>

<body>
  <div id="wrapper">
    <table align='center' cellspacing=2 cellpadding=5 id="data_table" border=1>
      <thead>
        <tr>
          <th>Name</th>
          <th>Level</th>
          <th>Action</th>
        </tr>
      </thead>
      <tbody id="table-rows">
        <tr>
          <td><input type="text" id="name-text"></td>
          <td>
            <select name="levels-list" id="levels-list">
    <option value="A" id="option-1">A</option>
    <option value="B" id="option-2">B</option>
    <option value="C" id="option-3">C</option>
    </select>
          </td>
          <td><input type="button" class="add" value="Add Row" id="add-button"></td>
        </tr>
    </tbody>
    </table>
  </div>
<script src="get-text.js"></script>
</body>

</html>

脚本:

var myArray = [{
  "name": "aaa",
  "level": "A"
}, {
  "name": "bbb",
  "level": "B"
}, {
  "name": "ccc",
  "level": "C"
}];


display();

function display() {
  var length = myArray.length;
  var htmlText = "";

  for (var i = 0; i < length; i++) {
    htmlText +=
      "<tr id='row" + i + "'>\
                <td>" + myArray[i].name + "</td>\
                <td>" + myArray[i].level + "</td>\
                <td>\
                    <input type='button' id='edit_button" + i + "' value='Edit' class='edit' onclick='editRow("+i+")'> \
                    <input type='button' id='save_button" + i + "' value='Save' class='save' onclick='save_row(" + i + ")'> \
                    <input type='button' value='Delete' class='delete' onclick='delete_row(" + i + ")'>\
                </td>\
            </tr>";
  }//end loop
  htmlText+=
  "<tr>\
    <td><input type='text' id='name-text'></td>\
    <td>\
      <select name='levels-list' id='levels-list'>\
        <option value='A' id='option-1'>A</option>\
        <option value='B' id='option-2'>B</option>\
        <option value='C' id='option-3'>C</option>\
        </select>\
    </td>\
    <td><input type='button' class='add' value='Add Row' id='add-button' ></td>\
  </tr>";

  document.getElementById("table-rows").innerHTML = htmlText;
}//end display

var addButton=document.getElementById("add-button");
addButton.addEventListener('click', addRow, false);

function addRow(){
  event.preventDefault();
  var newData= document.getElementById("name-text").value;
  var newLevel = document.getElementById("levels-list").value;

  var table = document.getElementById("data_table");
  var tableLength = (table.rows.length)-1;
//  console.log(tableLength);
  var row = table.insertRow(tableLength).innerHTML=
   "<tr id= 'row"+tableLength+"'>\
        <td id='name-text"+tableLength+"'>"+newData+"</td>\
        <td id='levels-list"+tableLength+"'>"+newLevel+"</td>\
        <td><input type='button' id='edit-button"+tableLength+"' value='Edit' class='edit' onclick='editRow("+tableLength+")'> \
            <input type='button' id='save-button"+tableLength+"' value='Save' class='save' onclick='saveRow("+tableLength+")'> \
            <input type='button' id= 'delete-button"+tableLength+"' value='Delete' class='delete' onclick='deleteRow("+tableLength+")'>\
        </td>\
   </tr>";

  document.getElementById("name-text").value="";
}//end addRow

function editRow(no)
{
  document.getElementById("edit-button"+no).disabled=true;
   //document.getElementById("save-button"+no).style.display="block";

   var name=document.getElementById("name-text"+no);
   var level=document.getElementById("levels-list"+no);

   var nameData=name.innerHTML;
   var levelData=level.innerHTML;

   name.innerHTML="<input type='text' id='name_text"+no+"' value='"+nameData+"'>";
   level.innerHTML='<select id="levels-list'+no+'">\
                      <option value="A" id="option-1">A</option>\
                      <option value="B" id="option-2">B</option>\
                      <option value="C" id="option-3">C</option>\
                      </select>' ;

  document.getElementById("levels-list"+no).value = levelData;
}

function deleteRow(no) {
  myArray.splice(no, 1);
  document.getElementById("row"+no).innerHTML="";
  //display();
} //end deleteRow

function saveRow(no)
{
  myArray[no].name = document.getElementById("name-text"+no).value;
  myArray[no].level = document.getElementById("levels-list"+no).value;

  document.getElementById("row"+no).innerHTML =
  "<tr id= 'row"+no+"'>\
    <td id='name-text"+no+"'>"+myArray[no].name+"</td>\
    <td id='levels-list"+no+"'>"+myArray[no].level+"</td>\
    <td><input type='button' id='edit-button"+no+"' value='Edit' class='edit' onclick='editRow("+no+")'> \
        <input type='button' value='Delete' class='delete' onclick='deleteRow("+no+")'>\
    </td>\
   </tr>";
}//end saveRow

【问题讨论】:

    标签: javascript html html-table dom-events


    【解决方案1】:

    我重构了一点你的代码并创建了一个新的 jsfiddle。你可以越来越多地重构它,如果可以在你的项目中插入 jQuery,你会简单很多。

    这么几条笔记:

    1) 让您的模型与您的 UI 更改保持同步。在前面的示例中,您正在操作 HTML,但没有更新数组模型

    2) 尽量将常用代码保留在函数中,以避免重复。 例如,我移动了在函数内创建行的逻辑,并且每次需要创建新行时都调用该函数(用于在开头显示和单击添加行时)

    3) 当你在行中调用你的函数时,也传递当前的 HTML 元素。您可以传递它以了解当前单击了哪个 HTML 元素,以便您可以轻松地操作该行。

    4) 使用两个 tbody。一个用于数据,另一个用于操作。它可以更轻松地将数据与操作区分开来,避免每次都重复该行以进行操作

    还有一些您可以单独使用代码检查的内容。

    您只需管理在正确操作中禁用按钮的逻辑,以避免例如在编辑时再次单击编辑,但自己动手是一个很好的练习:)

    这里是示例:

    var myArray = [{
      "name": "aaa",
      "level": "A"
    }, {
      "name": "bbb",
      "level": "B"
    }, {
      "name": "ccc",
      "level": "C"
    }];
    
    function createDataRow(el, ind) {
      var row = document.createElement('tr');
      row.id = 'row-' + ind;
      var cell1Content = `
      	<div class="name-content">${el.name}</div>
        <input class="name-edit" type="text" id="name-text-${ind}" value="${el.name}" style="display:none;">
      `;
      
      var cell2Content = `
      	<div class="level-content">${el.level}</div>
      	<select class="level-edit" id="levels-list-${ind}" style="display:none;">
          <option value="A">A</option>\
          <option value="B">B</option>\
          <option value="C">C</option>\
        </select>
      `;
      
      var cell3Content = `
        <input type="button" id='edit_button" + i + "' value="Edit" class="edit" onclick="editRow(this, ${ind})">
        <input type="button" id='save_button" + i + "' value="Save" class="save" onclick="saveRow(this, ${ind})">
        <input type="button" value="Delete" class="delete" onclick="deleteRow(this, ${ind})">
      `;
      var cell1 = row.insertCell(0);
      var cell2 = row.insertCell(1);
      var cell3 = row.insertCell(2);
      
      cell1.innerHTML = cell1Content;
      cell2.innerHTML = cell2Content;
      cell3.innerHTML = cell3Content;
      
      document.getElementById('table-data').appendChild(row);
    }
    
    function displayData() {
      myArray.forEach(function(el, ind) {
      	createDataRow(el,ind);
      });
    }
    
    function deleteRow(el, ind) {
    	el.parentElement.parentElement.parentElement.removeChild(el.parentElement.parentElement); 
      myArray.splice(ind, 1);
    }
    
    function addRow(){
      event.preventDefault();
      var newEl = {
      	"name": document.getElementById("name-text").value,
        "level": document.getElementById("levels-list").value
      };
      myArray.push(newEl);
      createDataRow(newEl, myArray.length - 1);
      document.getElementById("name-text").value = '';
      document.getElementById("levels-list").value = 'A';
    }//end addRow
    
    function editRow(el, ind)
    {
    	var currentRow = el.parentElement.parentElement;
      
      currentRow.cells[0].getElementsByClassName("name-content")[0].style.display = 'none';
      currentRow.cells[0].getElementsByClassName("name-edit")[0].style.display = 'block';
      
      currentRow.cells[1].getElementsByClassName("level-content")[0].style.display = 'none';
      currentRow.cells[1].getElementsByClassName("level-edit")[0].value = myArray[ind].level;
      currentRow.cells[1].getElementsByClassName("level-edit")[0].style.display = 'block';
    }
     //end deleteRow
    
    function saveRow(el, ind)
    {
    	var currentRow = el.parentElement.parentElement;
      
      var nameContent = currentRow.cells[0].getElementsByClassName("name-content")[0];
      var nameEdit = currentRow.cells[0].getElementsByClassName("name-edit")[0];
      nameContent.innerHTML = nameEdit.value;
      nameContent.style.display = 'block';
      nameEdit.style.display = 'none';
      
      var levelContent = currentRow.cells[1].getElementsByClassName("level-content")[0];
      var levelEdit = currentRow.cells[1].getElementsByClassName("level-edit")[0];
      levelContent.innerHTML = levelEdit.value;
      levelContent.style.display = 'block';
      levelEdit.style.display = 'none';
      
      myArray[ind].name = nameEdit.value;
      myArray[ind].level = levelEdit.value;
    }//end saveRow
    
    var addButton=document.getElementById("add-button");
    addButton.addEventListener('click', addRow, false);
    displayData();
    <body>
      <div id="wrapper">
        <table align='center' cellspacing=2 cellpadding=5 id="data_table" border=1>
          <thead>
            <tr>
              <th>Name</th>
              <th>Level</th>
              <th>Action</th>
            </tr>
          </thead>
          <tbody id="table-data">
          </tbody>
          <tbody id="table-rows">
            <tr>
              <td><input type="text" id="name-text"></td>
              <td>
                <select name="levels-list" id="levels-list">
                  <option value="A" id="option-1">A</option>
                  <option value="B" id="option-2">B</option>
                  <option value="C" id="option-3">C</option>
                </select>
              </td>
              <td><input type="button" class="add" value="Add Row" id="add-button"></td>
            </tr>
          </tbody>
        </table>
      </div>
    </body>

    这里是 jsfiddle(这次保存了 :D):

    https://jsfiddle.net/u0865zaa/8/

    我希望它有所帮助。如有任何疑问,请告诉我。

    【讨论】:

    • 谢谢。但是你所说的没有任何效果。您发布的修改与我发布的修改没有什么不同,并且不能解决问题。您提供的代码链接无法运行。
    • 好的。编辑现在有效。但是链接中的代码不是。没有一个按钮(保存、编辑、删除)正在执行该功能。
    • 我没有在 jsfiddle 上保存最新版本更新 URL -.-
    • 尝试重新创建正确的版本。删除也应该在我给你的链接中起作用
    • 好吧,我重构了一下示例并重新创建了 jsfiddle,更新了答案
    猜你喜欢
    • 1970-01-01
    • 2017-01-11
    • 2013-02-16
    • 2011-10-24
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 2018-03-15
    • 2010-10-07
    相关资源
    最近更新 更多