HTML和JavaScript动态表的问题 [英] Problems with HTML and javascript dynamic table
问题描述
我遇到以下问题:1)saveRow函数不保存行。我得到这个错误: Uncaught TypeError:不能在saveRow的HTMLInputElement.onclick
处设置undefined的属性名称。 2) deleteRow
不起作用。我得到一个类似的错误: Uncaught TypeError:无法设置属性'innerHTML'为null
。 3)在editRow中,我的字段变得可编辑,但使用之前保存的默认值。例如,列表总是A,B,C,这不是我想要的。我希望列表的初始值是之前选择的值。
我正在做的事情应该是错的。这里是代码:
HTML:
< html>
< head>
< / head>
< body>
< div id =wrapper>
< thead>
< tr>
< th>名称< / th>
< th> Level< / th>
< th>动作< / th>
< / tr>
< / thead>
< tbody id =table-rows>
< tr>
< td>< input type =textid =name-text>< / td>
< td>
< option value =Aid =option-1> A< / option>
< option value =Bid =option-2> B< / option>
< option value =Cid =option-3> C< / option>
< / select>
< / td>
< td>< input type =buttonclass =addvalue =Add Rowid =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();
函数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> \
< / td> \
< option>'C'id ='option-3'> C< / option> b $ b< td>< input type ='button'class ='add'value ='Add Row'id ='add-button'>< / td> \
< / tr> ;;
document.getElementById(table-rows)。innerHTML = htmlText;
} //结束显示
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 =Aid =option-1> A< / option> \
< option value =Bid =option-2> B< / option> \
< / select>';
document.getElementById(levels-list+ no).value = levelData;
}
函数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) 。值;
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 ='删除'class ='delete'onclick ='deleteRow(+ no +)'> ; \
< / td> \
< / tr>;
} // end saveRow
有点你的代码并创建了一个新的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}];函数createDataRow(el,ind){var row = document.createElement('tr'); row.id ='row-'+ ind; var cell1Content =`< div class =name-content> $ {el.name}< / div> < input class =name-edittype =textid =name-text - $ {ind}value =$ {el.name}style =display:none;> `; var cell2Content =`< div class =level-content> $ {el.level}< / div> < select class =level-editid =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 =buttonid ='edit_button+ i +'value =Editclass =editonclick =editRow(this,$ {ind})> < input type =buttonid ='save_button+ i +'value =Saveclass =saveonclick =saveRow(this,$ {ind})> < input type =buttonvalue =Deleteclass =deleteonclick =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; ()函数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(墩); createDataRow(newEl,myArray.length - 1); document.getElementById(name-text)。value =''; document.getElementById(levels-list)。value ='A';} // end addRowfunction 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';} //结束deleteRowfunction 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;} //结束saveRowvar addButton = document.getElementById(add-button); addButton.addEventListener('click',addRow,false); displayData();
< body> < div id =wrapper> < table align ='center'cellspacing = 2 cellpadding = 5 id =data_tableborder = 1> < THEAD> < TR> <的第i;姓名< /第> <第>级< /第> <的第i;动作< /第> < / TR> < / THEAD> < tbody id =table-data> < / tbody的> < tbody id =table-rows> < TR> < td>< input type =textid =name-text>< / td> < TD> < select name =levels-listid =levels-list> < option value =Aid =option-1> A< / option> < option value =Bid =option-2> B< / option> < option value =Cid =option-3> C< / option> < /选择> < / TD> < td>< input type =buttonclass =addvalue =Add Rowid =add-button>< / td> < / TR> < / tbody的> < /表> < / div>< / body>
jsfiddle(这次保存:D):
https ://jsfiddle.net/u0865zaa/8/
我希望它有帮助。对于任何疑问,请让我知道。
I am facing problems in: 1) the function saveRow does not save the row. I get this error: Uncaught TypeError: Cannot set property name of undefined at at saveRow at HTMLInputElement.onclick
. 2) the deleteRow
does not work. I get a similar error: Uncaught TypeError: Cannot set property 'innerHTML' of null
. 3) in the editRow, I fields to become editable, but with the default values as what was saved before. For example, the list is always A, B, C which is not what I want. I want the initial value of the list to be what was selected previously.
There should be something wrong I am doing. Here is the code:
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>
The script:
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
I refactored a bit your code and created a new jsfiddle. You can refactor it more and more, and if possible to insert jQuery in your project, you will simply it a lot more.
So few notes:
1) Keep you model up to date with your UI changes. In the before sample you were manipulating HTML but you were not updating the array model
2) Try to keep your common code in functions, in order to avoid repetitions. For example I moved the logic for creating row inside a function, and just calling that function every time that you need to create a new row (for displaying at the beginning and when clicking add row)
3) When you call your functions in the row, pass also the current HTML element. You can pass it in order to know which current HTML element has been clicked, so that you can easily manipulate that row.
4) Use two tbodies. One for the data and another one for the actions. It makes easier to distinct data from actions, avoiding to repeat every time also that row for actions
And few other things that you can check alone with the code.
You have to manage just the logic of disabling the buttons in the right operations, in order to avoid for example to click edit again when editing, but it would be a good exercise to do it yourself :)
Here the sample:
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>
And here the jsfiddle (this time saved :D ):
https://jsfiddle.net/u0865zaa/8/
I hope it helps. For any queries let me know.
这篇关于HTML和JavaScript动态表的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!