0
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>TEST</title>

<link rel="stylesheet" type="text/css" href="/js/jquery-ui-1.8.24.custom.css" media="screen, projection">
<script type="text/javascript" src="/js/jquery-1.8.2.js"></script>
<script type="text/javascript" src="/js/jquery-ui-1.8.24.custom.min.js"></script>


<script type="text/javascript">
<!--

function loadOperators(rowID)
{
    alert("ROW: " + rowID);
}

var lastRowID = 1;

// Add new row
$('input#addrow').live('click', function(){

    lastRowID += 1;

    var $clonedRow = $('tr#row_1').clone();

    // manipulating new ids for the elements in the newly created row
    $clonedRow.find('*').andSelf().filter('[id]').each(function() {
        var string = this.id;

        pos = string.lastIndexOf('_');

        var tempStr = string.substr(0, pos);

        this.id = tempStr + "_" + lastRowID;
    });

    $clonedRow.insertBefore("#clone_table tr#spacer_row");

    $("#field_id_" + lastRowID).on('change', function(){
        loadOperators(lastRowID);
    });

});



// Delete a row
$('input#delrow').live('click', function(){

    if(lastRowID == 1)
    {
        return;
    }

    $('tr#row_' + lastRowID).remove();

    lastRowID -= 1;
});



$(document).ready(function() {

    loadOperators(lastRowID);

    $("#field_id_1").on('change', function(){
        loadOperators(lastRowID);
    });
});

//-->
</script>

</head>

<body>

<table id="clone_table" width="700" cellpadding="0" border="0">

<colgroup>
    <col width="200">
    <col width="200">
    <col width="200">
</colgroup>

<tr id="row_1">
    <td>
        <select name="field_id_1" id="field_id_1">
            <option value="1">Item One</option>
            <option value="2">Item Two</option>
            <option value="3">Item Three</option>       
        </select>
    </td>

    <td id="operator_strip_1"></td>

    <td id="">&#160;</td>   
</tr>

<tr id="spacer_row"><td colspan="3">&#160;</td></tr>

<tr><td colspan="3">&#160;</td></tr>

<tr><td colspan="3"><input type="button" id="addrow" value="More" /> <input type="button" id="delrow" value="Less" /></td></tr>

</table>

</body>
</html>

I am trying to add and delete rows to a HTML table dynamically. But the generated row contains one combo box with a onchange event handler function. I need to pass the row ID to that function. When I assign the new ID to the latest combo box's onchange event handler, it is changing the value assigned to the already generated combo boxes also. Can anyone look this code and tell me what is causing the issue here?

1
  • .live is deprecated; just use .on instead. Commented Dec 29, 2013 at 13:12

1 Answer 1

1

When you reference lastRowID in the call to loadOperators, you're getting the current value, because the variable is not local to the click handler function. You don't need the variable, you can just use this.id.

$('input#addrow').live('click', function(){

    lastRowID += 1;

    var $clonedRow = $('tr#row_1').clone();

    // manipulating new ids for the elements in the newly created row
    $clonedRow.find('*').andSelf().filter('[id]').each(function() {
        var string = this.id;

        pos = string.lastIndexOf('_');

        var tempStr = string.substr(0, pos);

        this.id = tempStr + "_" + lastRowID;
    });

    $clonedRow.insertBefore("#clone_table tr#spacer_row");

    $("#field_id_" + lastRowID).on('change', function(){
        loadOperators(this.id);
    });

});

Instead of binding a handler every time you add a row, you could use delegation. Give all the field_id_N elements a class (field_class in the example below), and do this just once in the document.ready function:

$("#clone_table").on('change', '.field_class', function() {
    loadOperators(this.id);
});

I'm not sure what the real loadOperators() function does (the one in your question is obviously just a stub), but I suspect you could just pass this to it instead of the ID, and you could probably get rid of all IDs in the elements that get cloned.

If you really need the lastRowID value, you can copy it into a local variable, which will be captured in the closure.

$('input#addrow').live('click', function(){

    lastRowID += 1;
    var thisRowID = lastRowID;

    var $clonedRow = $('tr#row_1').clone();

    // manipulating new ids for the elements in the newly created row
    $clonedRow.find('*').andSelf().filter('[id]').each(function() {
        var string = this.id;

        pos = string.lastIndexOf('_');

        var tempStr = string.substr(0, pos);

        this.id = tempStr + "_" + lastRowID;
    });

    $clonedRow.insertBefore("#clone_table tr#spacer_row");

    $("#field_id_" + lastRowID).on('change', function(){
        loadOperators(thisRowID);
    });

});
Sign up to request clarification or add additional context in comments.

2 Comments

'loadOperators' needs the argument value: 1, 2, 3,.. etc. for each combo box instead of 'this.id'. I did not understand the problem of global variable 'lastRowID'. Whenever I add a new combo box(ie, on each Add button click), I am using the current value of 'lastRowID' to set the value to the new combo box's 'loadOperators' function.
Thank you for your answer. Is there any other way around for using the lastRowID instead of this.id?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.