JQuery AutoComplete and Clone

2020-07-11 09:17发布

问题:

I have an issue trying to apply jQuery AutoComplete to multiple rows in a table when using jQuery clone. The AutoComplete works on the first row but fails to work when additional rows are added to the table. So far, I have the following:

HTML Table:

    <table class="table" cellspacing="0" id="myTable">
      <tr> 
        <th width="40%">Item</th> 
        <th width="60%">Description</th> 
      </tr> 
      <tr>
        <td>input name="product_title" id="product_title" type="text"><td> 
        <td><textarea name="product_description" id="product_description"></textarea></td> 
      </tr> 
    </table>
   <input type="button" value="Add Row" onclick="javascript:addRow()">

Clone Script:

function addRow(){
  $('#myTable tr:last').clone(true).insertAfter('#myTable tr:last');
  $('#myTable tr:last input').val("");
  $('#myTable tr:last input:first').focus();        
}

AutoComplete script:

$().ready(function() {
  $("#product_title").autocomplete(products, {
    width: 380,
    matchContains: "word",
    formatItem: function(row) {
      return row.title;
    }
  });   
  $('#product_title').result(function(event, data) {
  $('#product_description').val(data.description);
  });   
});

The data for the autocomplete is pulled from a simple MySQL query which defines the product title and description.

At the moment, the add new row works fine and so does the AutoComplete for the first row of the table, however it fails to work on any additional rows that are added. Even if I add a second row manually to the HTML table, the AutoComplete doesn't work on this either.

Does anybody know if there is an (easy) way to modify the above code to make this work? I'm a novice when it comes to jQuery so the more details, the better.

Thanks in advance!!!

回答1:

This is a common issue using plugins on dynamically added elements. It usually requires calling the plugin on the new elements after they are inserted in the DOM. Instead of duplicating the same code for the initial page load elements and new elements, you can usually create a simple helper function that uses a parent element as the main reference and searches only within that element for the elements to apply the plugin to.

Important: You are repeating ID's when you clone new rows and ID's must be unique in a page by definition. The following code changes your ID's to class instead and you will need to do same in your markup.

var $table;
$(function() {
     $table=$('#myTable'); 
     var $existRow=$table.find('tr').eq(1);
      /* bind to existing elements on page load*/
      bindAutoComplete($existRow);
});

function addRow(){
    var $row=$table.find('tr:last').clone(true);
    var $input=$row.find('input').val("");
    $table.append($row);
    bindAutoComplete($row );
    $input.focus();

}


function bindAutoComplete($row ){
    /* use row as main element to save traversing back up from input*/
    $row.find(".product_title").autocomplete(products, {
        width: 380,
        matchContains: "word",
        formatItem: function(row) {
            return row.title;
        }
    });
    $row.find('.product_title').result(function(event, data) {
        $row.find('.product_description').val(data.description);
    });
}


回答2:

I think the problem is, with clone(), you clone an element, which already have the autocomplete properties and then autocomplete can't add "again" to the new element. I think you should not clone(), you should use the original HTML code of the element and put it in.

EDIT:

How I fixed it:

  1. autocomplete("destroy") for the orginal input field you would like to clone.
  2. Clone your element and add the autocomplete to it

And don't use clone(true), but you can use clone()



回答3:

Charlietfl's post solved my problem, the only change I had to make was replacing:

var $row=$table.find('tr:last').clone(true);

with

var $row=$table.find('tr:last').clone();removing the true.

Hope this helps somebody else :)