jQuery/Javascript Help: Cannot get dynamically added fields with autocomplete to work

Viewed 56

I am quite new to jQuery and javascript and am having a difficult time understanding the various examples and code snippets I'm finding online.

One of the main functionalities of my Flask site is a form which allows users to dynamically add as many fields as they want, and each of these fields gives autocomplete options based on the database.

Using examples found online, I have been able to create a form which has dynamically added options (however my understanding of how it works is very subpar).

I have also found examples for autocomplete which when tweaked worked for individual fields. However, I have the issue that when these are put together (autocomplete and dynamically added fields), the first field of the form is the only one that autocompletes. Could anyone give me insight into how I could fix this or what I'm doing wrong? I've been trying for days now to figure this out and I feel like I've hit a brick wall.

Here is the snippet of code which currently allows me to autocomplete a single field:

<script type="text/javascript">
        $(function() {
            $("#autocomplete").autocomplete({
                source:function(request, response) {
                    $.getJSON("{{url_for('fruit.autocomplete')}}",{
                        q: request.term,
                    }, function(data) {
                        response(data.matching_results);
                    });
                },
                minLength: 2,
                select: function(event, ui) {
                    console.log(ui.item.value);
                }
            });
        })
</script>

The getJSON calls fruit.autocomplete which is as shown:

@fruit.route('/autocomplete', methods=['GET'])
def autocomplete():
    search = request.args.get('q')
    query = Fruit.query.filter(Fruit.name.like('%' + str(search) + '%'))
    results = []
    for fruit in query:
        result = fruit.as_dict()
        results.append(result)
    return jsonify(matching_results=results)

To autocomplete, its a case of adding: id="autocomplete" to a field in a form.

Additionally, here is the snippet of code which currently allows me to dynamically add fields to a form (but subsequently can't autocomplete the additionally fields besides the first one), but with two errors regularly appearing:

"Uncaught TypeError: this.source is not a function"

"Uncaught (in promise) TypeError: Cannot read property 'toString' of undefined"

<script>
$(document).ready(function(){
    var max_input_fields = 20;
    var add_input = $('.add-input');
    var input_wrapper = $('.input-wrapper');
    var new_input = '<div><input class="form-control" id="autocomplete" type="text" name="field[]" value=""/><a href="javascript:void(0);" class="remove-input" title="Remove input">-</a></div>';
    var add_input_count = 1;
    $(add_input).click(function(){
        if(add_input_count < max_input_fields){
            add_input_count++;
            $(input_wrapper).append(new_input).autocomplete();
        }
    });
    $(input_wrapper).on('click', '.remove-input', function(e){
        e.preventDefault();
        $(this).parent('div').remove();
        add_input_count--;
    });
});
</script>
<form action="" method="POST" enctype="">
    <div class="input-wrapper">
        <div>
            Fruit: <br/>
            <input class="form-control" id="autocomplete" type="text" name="field[]" value="" autocomplete="off"/>
            <a href="javascript:void(0);" class="add-input" title="Add input">+</a>
        </div>
    </div>
    <input class="btn btn-outline-info" type="submit" name="cmdsubmit">
</form>

I'm just looking for a simple way that I can implement these two features at the same time, and I am very open to different methods/suggestions of how to achieve it, the code examples above are purely resources I have found online which seemed to work

Any help is greatly appreciated! Thank you!

1 Answers

You are using same id for mutliple elements so change that to class . Then, you need to initialize the inputs which are dynamically added so for that you can use find(".autocomplete:last").autocomplete(options) this line will find last autocomplete input added and then initialize same .

Demo Code :

$(document).ready(function() {
  //because this will use mutliple times..
  var options = {
    source: [{
          "value": "Abcde",
        },
        {
          "value": "Xyzmn",
        },
        {
          "value": "DEfwe",
        }
      ] //this is for demo..remove above uncomment below to use
      /*function(request, response) {
            $.getJSON("{{url_for('fruit.autocomplete')}}", {
              q: request.term,
            }, function(data) {
      response(data.matching_results);
      });
    }*/
      ,
    minLength: 2,
    select: function(event, ui) {
      console.log(ui.item.value);
    }
  }

  var max_input_fields = 20;
  var add_input = $('.add-input');
  var input_wrapper = $('.input-wrapper');
  var new_input = '<div><input class="form-control autocomplete" type="text" name="field[]" value=""/><a href="javascript:void(0);" class="remove-input" title="Remove input">-</a></div>';
  var add_input_count = 1;
  $(add_input).click(function() {
    if (add_input_count < max_input_fields) {
      add_input_count++;
      $(input_wrapper).append(new_input)
      //get last input added ..intialize it
      $(input_wrapper).find(".autocomplete:last").autocomplete(options)
    }
  });
  $(input_wrapper).on('click', '.remove-input', function(e) {
    e.preventDefault();
    $(this).parent('div').remove();
    add_input_count--;
  });
  //your main input.
  $("#autocomplete").autocomplete(options);

});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<form action="" method="POST" enctype="">
  <div class="input-wrapper">
    <div>
      Fruit: <br/>
      <input class="form-control" id="autocomplete" type="text" name="field[]" value="" autocomplete="off" />
      <a href="javascript:void(0);" class="add-input" title="Add input">+</a>
    </div>
  </div>
  <input class="btn btn-outline-info" type="submit" name="cmdsubmit">
</form>

Related