我有一个表格,其中单元格包含嵌入的输入元素。 (这是一项正在进行中的工作,所以请忽略空ID等,但我想在运行时粘贴实际代码):
<table class='table table-bordered table-hover table-condensed' id='esr_table'>
<thead>
<tr>
<th class='macd_action'>Action</th>
<th class='macd_action'>Hostname</th>
<th class='macd_action'>IP Address</th>
<th class='macd_action'>Model</th>
<th class='clickme tw15' id='add_row'>
<span class='<% entry.0 %>_span glyphicon glyphicon-plus'>
</span>
</th>
</tr>
</thead>
<tbody id="esr_table_body">
<tr>
<td class='' id=''>
<select>
<option value='Add'>Add</option>
<option value='Decommision'>Decommision</option>
<option value='Change'>Change</option>
</select>
</td>
<td class='' id=''>
<input type='text' placeholder='hostname' id='host' name='host'></input>
</td>
<td class='' id=''>
<input type='text' placeholder='0.0.0.0' id='ipaddress' name='ipaddress'></input>
</td>
<td class='' id=''>
<input type='text' placeholder='model' id='model' name='model'></input>
</td>
<td class='clickme minus' id=''>
<span class='minus glyphicon glyphicon-minus'></span>
</td>
</tr>
</tbody>
</table>
我从另一个来源抓取数据并通过ajax将其发送到服务器进行处理。服务器将数据作为存储在var动作中的二维数组返回。我的ajax成功函数如下所示:
success: function(dat){
var actCount = actions.length;
var rowCount = $('#esr_table_body tr').length;
for(var i = 0; i < actCount - rowCount; i++) {
$('#esr_table > tbody:last-child').append(trow);
}
var tbl = document.getElementById('esr_table_body');
for(var i = 0; i <= actCount; i++){
var rw = tbl.rows[i];
for(var j = 0; j < 4; j++){
rw.cells[j].firstChild.value = actions[i][j];
}
}
}
除了一个问题外,这个工作正常 - 表的第一行保持空白。动态添加的表将填充数据并正确显示它。表的第二行包含第二行返回的数据等。我已经验证了返回的数据是正确的。它没有错过第一行。如果我将此行更改为“小于或等于”:
for(var i = 0; i < actCount - rowCount; i++) {
将额外的行添加到表中。如果我然后改变这一行:
var rw = tbl.rows[i];
到[i + 1]然后循环开始在第1行而不是第0行更新,并显示所有返回的数据。此外,如果我将表更改为具有两个静态行,则前两行保持空白,表的第三行使用返回数据的第三行进行更新。因此,我能看到的所有内容都表明更新正在处理动态生成的行,但要么不在静态行上工作,要么正在更新值,但不会刷新显示。动态更新会插入一个与页面上的静态HTML相同的字符串。我甚至将静态HTML和字符串粘贴到拆分窗口中并完成vimdiff以验证HTML是否相同。我在多个浏览器上试过这个并看到相同的行为。我完全难过了,几个小时的谷歌搜索没有让我更明智地知道这个问题是什么。我很感激你的帮助。
更新:我越是关注它,它就越奇怪。如果转到jsfiddle并单击按钮,则表的第一行(应为索引0)为空。单元格中没有显示任何值。但是如果你打开控制台,你可以这样做:
var esrTable = document.getElementById("esr_table_body").children;
undefined
esrTable[0].cells[1].firstChild.value
"Host1"
所以我可以检索我指定的值,但它没有显示在页面上?我甚至不能。
答案 0 :(得分:0)
我通过清空tbody HTML(删除那里的单行)并使脚本在开头添加行来修复它。
var trow = "..."; $('#esr_table > tbody:last-child').append(trow); function upd() { ... }
否则表格显然甚至没有意识到它的第一行应该是索引0(即行[0]是未定义的),由此判断:
未捕获的TypeError:无法读取未定义的属性“单元格”
每次点击仅打印一次(而不是4次)。你所说的从1工作开始的循环也支持这一点。
<强>更新强>
真正的解决方案是使行的HTML代码更紧凑,否则单元格中的第一个子节点将是包含空格的文本节点:
<td class='' id=''><input type='text' placeholder='hostname' id='host' name='host'/></td>
<td class='' id=''><input type='text' placeholder='0.0.0.0' id='ipaddress' name='ipaddress'/></td>
<td class='' id=''><input type='text' placeholder='model' id='model' name='model'/></td>
<td class='clickme minus' id=''><span class='minus glyphicon glyphicon-minus'></span></td>
...或者如果您希望保持HTML整洁,而是使用Javascript来解决此问题:
for (var i = 0; i < actCount; i++) {
var rw = tbl.rows[i];
for (var j = 0; j < 4; j++) {
if(rw.cells[j].firstChild.nodeType == 3) {
//nodeType is 3 for text nodes -- SHOW NO MERCY TO THEM
rw.cells[j].removeChild(rw.cells[j].firstChild);
}
rw.cells[j].firstChild.value = actions[i][j];
}
}
当然,最好只修改行中的行,而不是每次点击的每一行,但这取决于您的实现和目标。
注意:此外,未定义的行实际上是由i循环从0变为actCount而不是从0变为actCount-1。