简体   繁体   中英

Text input in table not updating when value changed via javascript

I have a table where the cells contain embedded input elements. (This is a work in progress, so please ignore the empty id's, etc. but I wanted to paste the actual code as I'm running it):

<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>

I'm grabbing data from another source and sending it to the server via ajax for processing. The server returns the data as a two dimensional array stored in var actions. My ajax success function looks like this:

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];
        }
    }
}

This works fine except for one problem - the first row of the table remains blank. The dynamically added tables are populated with the data and correctly display it. The second row of the table contains the second row of returned data, etc. I've verified that the data being returned is correct. It's not missing the first row. If I change this line to 'less than or equals':

for(var i = 0; i < actCount - rowCount; i++) {

an extra row gets added to the table. If I then change this line:

 var rw = tbl.rows[i];

to [i+1] then the loop starts updating at row 1 instead of row 0 and all of the returned data is displayed. Furthermore, if I change the table to have two static rows, then the first two rows remain blank and the third row of the table is updated with the third row of returned data. So everything I can see indicates that the updates are working on the dynamically generated rows but are either not working on the static rows or the value is being updated but the display is not being refreshed. The dynamic update inserts a string which is identical to the static HTML on the page. I've even pasted the static HTML and the string into a split window and done a vimdiff to verify that the HTML is identical. I've tried this on multiple browsers and see the same behavior. I'm completely stumped and a couple of hours of Googling haven't left me any wiser as to what the issue could be. I'd be grateful for any assistance.

Update: The more I look into this, the weirder it gets. If you go to the jsfiddle and click the button, the first row fo the table, which should be index 0, is blank. There is no value displayed in the cells. But if you then open the console, you can do this:

var esrTable = document.getElementById("esr_table_body").children;
undefined
esrTable[0].cells[1].firstChild.value
"Host1"

So I can retrieve the value I assigned but it's not displayed on the page? I can't even.

I fixed it by emptying the tbody HTML (deleting the single row that was there) and making the script add the row in the beginning instead.

var trow = "..."; 

$('#esr_table > tbody:last-child').append(trow);

function upd() {
    ...
}

Otherwise the table obviously doesn't even realize its first row should be with index 0 (ie rows[0] is undefined), judging by this:

Uncaught TypeError: Cannot read property 'cells' of undefined

which is printed only once per click (as opposed to 4 times). What you said about the cycle starting at 1 working also supports this.

UPDATE

The real solution is making the HTML code for the row more compact, because otherwise the first children in the cells would be text nodes containing whitespace:

    <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>

...or if you prefer keeping your HTML neat and tidy and instead using Javascript to fix this:

  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];
    }
  }

Of course, it's better to just fix the row in the beginning, not every row on every click, but that depends on your implementation and goal.

Note: Also, the row that was undefined was actually caused by the i-cycle going from 0 to actCount instead of from 0 to actCount-1.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM