0

I'm doing an autocomplete functionality which fills a datalist with options comprised of an endpoint query, which is working properly. But I have a problem in the end of my ajax call where my function is affecting only the last element of an array, as opposed to the correct one that is being clicked. I'm trying to make sure that when the user clicks their selection in the list, it sends certain values of the object into form input fields to save.

Right now, when i click an option it does put the correct object values into the form, HOWEVER, they are the values that correspond to the final element in the array and not the clicked one.

I've commented where my issue starts, but this is the whole script for reference. Again, the list fills correctly (though a little slow) and the click does fill out the form inputs, but the values are not corresponding to the clicked option, just the last in the array.

What am I doing wrong here?

<script type="text/javascript">

//If user types, send their input in ajax POST on each keystroke
$('#productInput').on('input', function(){
    if($(this).val() === ''){
       return;
    }else{

        //their input is searchResult
       const searchResult = $(this).val(); 

       $.ajax({ //url
                data: {
                    search_result:searchResult
                },
                type: "POST", 
                success: function(response){

                    //empty out old responses
                    $('#returnedProducts').empty();

                    //this starts my index
                    let searchResult = response.hits.hits;
                    for(let i = 0; i < searchResult.length; i++) {

                        //this puts matches into the datalist option, which works
                        $("#returnedProducts").append("<option value=" + searchResult[i]._source.category + ">" + searchResult[i]._source.category + "</option>");

                        /*This block is my issue*/
                        $("#productInput").on('input', function(){
                            var val = this.val = this.value;
                            if($('#returnedProducts option').filter(function(){
                                return this.value === val;
                            }).length){
                                //These elements do fill, but the values correspond to only the last array item, not the clicked one 
                                document.getElementById("grpName").value = searchResult[i]._source.frm.grp.grp_name;
                                document.getElementById("grpNum").value = searchResult[i]._source.frm.grp.grp_code;              

                            }
                        }) 
                        /*end of problem block*/ 
                    }
                }
            });
    }

});
</script>
6
  • U should probably stick with jquery if you are using it rather than mixing in document.getElementById, for readability and such. And maybe avoid using potentially ambiguous statements such as var val = this.val = this.value; And you might end up solving the problem as well. Commented Aug 29, 2018 at 17:51
  • Fair points for sure, I'll probably refactor a bit for those issues as well. I'm just wondering if my current issue has to do with setting the [i] and not passing it into my problem function Commented Aug 29, 2018 at 18:08
  • for each search result which is returned, you add another "input" event handler function to the "productInput" element. So if there are 5 results, you create 5 more event handlers. Then when something is input into that box, all 5 handlers (plus the original one, so 6) will execute simultaneously. Pretty sure that's not even close to what you wanted. Commented Aug 29, 2018 at 18:52
  • You're adding options to the "returnedproducts" select list, and when the user selects an option you want some data to go into a form, is that right? Maybe better to handle the "change" event of the select list then (and handle it once outside of your "success" function!!), and set data attributes on the option for the extra values. When the change event runs, retrieve the data attributes from the currently selected option and use those to populate your form. Commented Aug 29, 2018 at 18:53
  • Is there any way you can work that into an example? Commented Aug 29, 2018 at 18:58

1 Answer 1

1

The problem is that for each search result which is returned, you add another "input" event handler function to the "productInput" element. So if there are 5 results, you create 5 more event handlers. Then when something is input into that box, all 5 handlers (plus the original one, so 6) will execute in sequence. Since each time it overwrites the same textboxes, hence you only ever see the the last value. I'm pretty sure that's not even close to what you wanted.

You're adding options to the "returnedProducts" select list, and when the user selects an option you want some data to go into a form, is that right? If so, it would make more sense to handle the "change" event of the select list (and handle it once outside of your "success" function!!), and set data attributes on the option for the extra values. When the change event runs, retrieve the data attributes from the currently selected option and use those to populate your form.

Here's the general idea:

In the loop through your results:

for(let i = 0; i < searchResult.length; i++) {
    //this puts matches into the select list option
    $("#returnedProducts").append("<option value='" + searchResult[i]._source.category + "' data-grpName='" + searchResult[i]._source.frm.grp.grp_name + "' data-grpNum='" + searchResult[i]._source.frm.grp.grp_code + "'>" + searchResult[i]._source.category + "</option>");
}

Then separately (outside your $('#productInput').on('input', function(){ block entirely):

$("#returnedProducts").change(function() {
  var selectedOption = $(this).find("option:selected");
  $("#grpName").val(selectedOption.data("grpName"));
  $("#grpNum").val(selectedOption.data("grpNum"));
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, I believe that set it straight

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.