tablas - Problemas con HTML y javascript dynamic table
tablas dinamicas html javascript (1)
Estoy enfrentando problemas en: 1) la función saveRow no guarda la fila. Obtengo este error: Uncaught TypeError: Cannot set property name of undefined at at saveRow at HTMLInputElement.onclick
. 2) el deleteRow
no funciona. Aparece un error similar: Uncaught TypeError: Cannot set property ''innerHTML'' of null
. 3) en editRow, I campos para ser editable, pero con los valores predeterminados como lo que se guardó antes. Por ejemplo, la lista siempre es A, B, C, que no es lo que quiero. Quiero que el valor inicial de la lista sea el que se seleccionó anteriormente. Debería haber algo mal que estoy haciendo. Aquí está el código:
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>
La secuencia de comandos:
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
Refactoreé un poco su código y creé un nuevo jsfiddle. Puede refactorizarlo cada vez más, y si es posible insertar jQuery en su proyecto, simplemente lo hará mucho más.
Tan pocas notas:
1) Mantenga su modelo actualizado con sus cambios de UI. En la muestra anterior estaba manipulando HTML pero no estaba actualizando el modelo de matriz
2) Trate de mantener su código común en funciones, para evitar repeticiones. Por ejemplo, moví la lógica para crear filas dentro de una función y llamé a esa función cada vez que necesitaba crear una nueva fila (para mostrar al principio y al hacer clic en agregar fila)
3) Cuando llame a sus funciones en la fila, pase también el elemento HTML actual. Puede pasarlo para saber en qué elemento HTML actual se ha hecho clic, para que pueda manipular fácilmente esa fila.
4) Usa dos cuerpos. Uno para los datos y otro para las acciones. Hace más fácil diferenciar los datos de las acciones, evitando repetir cada vez también esa fila para las acciones
Y algunas otras cosas que puedes verificar solo con el código.
Tienes que administrar solo la lógica de deshabilitar los botones en las operaciones correctas, para evitar, por ejemplo, hacer clic nuevamente en editar al editar, pero sería un buen ejercicio hacerlo tú mismo :)
Aquí la muestra:
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>
Y aquí el jsfiddle (esta vez guardado: D):
https://jsfiddle.net/u0865zaa/8/
Espero que ayude. Para cualquier consulta, házmelo saber.