0

I've now worked on this for 3 days, searching high and low for a solution without success.

I have a dynamic HTML table that has 5 inputs in a row. The inputs are named in the array convention (i.e. name=part_no[], name=cost[], and so on). Using jQuery, a button is displayed at the end of the initial row that allows the user to add a new row. When a new row is added, another button is created to allow the user to remove the row. Here is the code for the table and "add row" button:

<div class="row">
  <table id="part_numbers" class="table">
    <tbody>
      <tr>
        <td width="16.66%">
          <!--part number-->
          <label for="part_no[]" class="control-label">Part No</label>
          <input class="form-control part_no" type="text" name="part_no[]">
        </td>
        <td width="16.66%">
          <!--list price-->
          <label for="list_price[]" class="control-label">Suggested List Price</label>
          <span class="calc_prices" data-toggle="popover" title="Calculated Pricing" data-content="This is where the data will go" data-placement="top"><i class="fa fa-question-circle" aria-hidden="true"></i></span>
          <input class="form-control" type="text" name="list_price[]">
        </td>
        <td width="16.66%">
          <!--lot charge-->
          <label for="lot_charge[]" class="control-label">Lot Charge</label>
          <input class="form-control" type="text" name="lot_charge[]">
        </td>
        <td width="16.66%">
          <!--lead time eng-->
          <label for="lead_time_eng[]" class="control-label">Lead Time (ENG)</label>
          <input class="form-control" type="text" id="lead_time_eng[]" name="lead_time_eng[]">
        </td>
        <td width="16.66%">
          <!--lead time production-->
          <label for="lead_time_prod[]" class="control-label">Lead Time (PROD)</label>
          <input class="form-control" type="text" id="lead_time_prod[]" name="lead_time_prod[]">
        </td>
        <td width="16.66%">&nbsp;</td>
      </tr>
    </tbody>
  </table>
</div>
<div class="row">
  <div class="col-sm-12">
    <a href="javascript: void(0);" class="btn btn-success btn-sm hidden-print addCF">Add Row</a>
  </div>
</div>

Here is the code to add and remove a new row:

$('.addCF').click(function(e) {
    e.preventDefault();
    $('#part_numbers').append('<tr><td width="16.66%"><input class="form-control part_no" type="text" name="part_no[]"></td><td width="16.66%"><input class="form-control" type="text" name="list_price[]"></td><td width="16.66%"><input class="form-control" type="text" name="lot_charge[]"></td><td width="16.66%"><input class="form-control" type="text" name="lead_time_eng[]"></td><td width="16.66%"><input class="form-control" type="text" name="lead_time_prod[]"></td><td width="16.66%"><a href="javascript:void(0)" class="btn btn-danger btn-sm hidden-print remCF">Remove</a></td></tr>');
});
$('#part_numbers').on('click', '.remCF', function(e) {
    e.preventDefault();
    $(this).parent().parent().remove();
});

When the user starts typing in the part_no field, autocomplete is triggered and a list of matching part numbers are shown. When a part is selected, I'm updating a popover with calculated pricing.

I have no issues bringing the data in on the first row - autocomplete works perfectly, and the popover is updated. However when a new row is added and I start typing in the "part_no[]" field, autocomplete does not trigger. I've tried every variation I can think of for iterating through the input fields to trigger the autocomplete and nothing works.

Here is the autocomplete code. jQuery version is 2.03. jQuery UI version is 1.12.1. Any help is greatly appreciated:

$("[name^=part_no").each(function(index) {
        $(this).on('focus',function() {
            $(this).autocomplete({
            delay: 500,
            minLength: 3,
            autoFocus: true,
            source: "items.php",
            select: function(event, ui) {
                event.preventDefault();
                var item_no = ui.item.label;
                var std_cost = ui.item.std_cost;
                var std_part_price = ui.item.std_part_price;
                var custom_price = ui.item.custom_price;
                var existing_price = ui.item.existing_price;

                $(this).val(item_no);
                $('.calc_prices').popover("destroy").popover({
                    trigger: 'manual'
                }).popover("show").on('shown.bs.popover', function() {
                    $('.popover-title').text("Calculated Pricing for " + item_no);
                    $('.popover-title').append('<button type="button" class="close popovercloseid">&times;</button>');
                    var popover = $(this);
                    var contentEl = popover.next(".popover").find(".popover-content");
                    contentEl.html("Cost: " + std_cost + "<br />Standard: " + std_part_price + "<br />Custom: " + custom_price + "<br />Existing: " + existing_price);
                })
                return false;
            },
            change: function(event, ui) {
                event.preventDefault();
                var item_no = ui.item.label;
                var std_cost = ui.item.std_cost;
                var std_part_price = ui.item.std_part_price;
                var custom_price = ui.item.custom_price;
                var existing_price = ui.item.existing_price;

                $(this).val(item_no);
                $(".calc_prices").popover("destroy").popover({
                    trigger: 'manual'
                }).popover("show").on("shown.bs.popover", function() {
                    $(".popover-title").text("Calculated Pricing for " + item_no);
                    $(".popover-title").append('<button id="popovercloseid" type="button" class="close">&times;</button>');
                    var popover = $(this);
                    var contentEl = popover.next(".popover").find(".popover-content");
                    contentEl.html("Cost: " + std_cost + "<br />Standard: " + std_part_price + "<br />Custom: " + custom_price + "<br />Existing: " + existing_price);
                })
                return false;
            }
            });
        });
    });
1

2 Answers 2

1

You can use different approach for doing so. One of thing that you can do is initialize the autocomplete after new row has been added.

function enableAutoComplete($element) {
    $element.autocomplete({
      .....................
    });
  }

You can now use this function when you are adding new row using last selector option.

$('.addCF').click(function(e) {
    e.preventDefault();
    $('#part_numbers').append('<tr><td width="16.66%"><input class="form-control part_no" type="text" name="part_no[]"></td><td width="16.66%"><input class="form-control" type="text" name="list_price[]"></td><td width="16.66%"><input class="form-control" type="text" name="lot_charge[]"></td><td width="16.66%"><input class="form-control" type="text" name="lead_time_eng[]"></td><td width="16.66%"><input class="form-control" type="text" name="lead_time_prod[]"></td><td width="16.66%"><a href="javascript:void(0)" class="btn btn-danger btn-sm hidden-print remCF">Remove</a></td></tr>');
    enableAutoComplete($("[name^=part_no]:last"));
  });

And, You can use the same function to enable autocomplete on table initialization phase,

  $("[name^=part_no").each(function(index) {
    enableAutoComplete($(this));
  });

See the working fiddle here.

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

2 Comments

This worked perfectly! Thank you so much. Quick question - was it not working before because the script couldn't identify the row to apply to autocomplete to?
I did try your code before. But, As you were using For Each Statement to initialize the autocomplete plugin on dom ready/single time only. The newly created input won't be affected by it.
0

Use the clone to get the behavior on the new row instead.

$('.addCF').click(function(e) {
    e.preventDefault();
    var mytable = $('#part_numbers');
    var newrow = mytable.find('tr').eq(0).clone(true);
    newrow.find('td').last().html('<a href="javascript:void(0)" class="btn btn-danger btn-sm hidden-print remCF">Remove</a>');
    mytable.append(newrow);
});

I tested this in your fiddle, replacing the "new row" function you had.

NOTE: you can simplify this even more by adding the text for the remove button from the add function to your original markup, then hiding the button on the first row, showing it on others.

Revised to do that:

$('.addCF').click(function(e) {
    e.preventDefault();
    var mytable = $('#part_numbers');
    var newrow = mytable.find('tr').eq(0).clone(true);
    newrow.find('td').last().find('.remCF').show();
    mytable.append(newrow);
});
$('#part_numbers').find('tr').first().find('td').find('.remCF').hide();

This is a side item but you want a button use a button

OLD: <a href="javascript:void(0)" class="btn btn-danger btn-sm hidden-print remCF">Remove</a>

New: <button class="btn btn-danger btn-sm hidden-print remCF">Remove</button>

1 Comment

Thank you for the suggestion. I'm definitely going to implement the combination of the add & remove functionality. I appreciate your time.

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.