You are viewing limited content. For full access, please sign in.

Question

Question

API Data within Collection

asked on June 29, 2022

Hi,

I have the following code that autocompletes an address then returns using Bing API. Once the user selects the address, the longitude is sent to an input field. Everything works, but I am running into issues when implementing the code in fields that are in a collection. Whenever I add a new “set” in the collection, I was able to get the “address input” to be unique per set, but the coordinates field value is set to the new search in every “latitude” field. I am sure there is an issue with my JavaScript code. A possible solution to this is to send separate request to the API, but since I am trying to limit the number of calls to the API, I am hoping to avoid this.

The reason I need the coordinates is because I use those values in a separate API search to calculate the distance between two address. The form I am building is a mileage reimbursement form that automatically calculates the reimbursement amount base on where the employee went.

Below is the code I am using to autocomplete the address, it’s a portion of the code. For obvious reasons I have removed the api key from the code.

Bing rest api= https://docs.microsoft.com/en-us/bingmaps/rest-services/

Any help with this would be greatly appreciated.

 

 

 

$(document).ready(function(){
  $('.travelInfoCollection').on('blur', 'input', addressAutoComplete);
  function addressAutoComplete(){
      $('.addressInput1 input').each(function () {
        var objSet =  $(this);
        objSet.autocomplete({
          source: function (request, response) {
            $.ajax({
              url: "https://dev.virtualearth.net/REST/v1/Locations",
              dataType: "jsonp",
              data: {
                key: "<API KEY GOES HERE>",
                q: request.term
              },
              jsonp: "jsonp",
              
              success: function (data) {
                var result = data.resourceSets[0];
                if (result) {
                  if (result.estimatedTotal > 0) {
                    response($.map(result.resources, function (item) {
                      return {
                        data: item,
                        label: item.name + ' (' + item.address.countryRegion + ')',
                        value: item.name + ' (Latitude: ' + item.point.coordinates[0] + ' Longitude: ' + item.point.coordinates[1] + ')'
                      }
                    }));
                  }
                }
              }
            });
          },
          minLength: 1,
          change: function (event, ui) {
            if (!ui.item)
              objSet.val('');
          },
          
          select: function (event, ui) {
           displaySelectedItem1(ui.item.data);          
          }
        });

        function displaySelectedItem1(item) {
          $('.fromLat input').val(item.point.coordinates[0]);
        } 
      });
  }
});

 

Capture.PNG
Capture.PNG (21.9 KB)
1 0

Answer

SELECTED ANSWER
replied on June 29, 2022

That's great!  Unlike the original code that was cycling through each one of the addressInput1 fields - your new code is only looking at the instance of addressInput1 that specifically was changed.

0 0

Replies

replied on June 29, 2022

The problem with your update code is that with a collection, the field has an index applied and you are not using the index at all.

 

See Table and Collection JavaScript Event Handlers for a better explanation.

2 0
replied on June 29, 2022

Hi Bert, 

 

Thank you for that, I updated the line to:

 

$('ul.rpx .fromLat input').val(item.point.coordinates[0]);

but the issues still persist, when a new set is added, it rewrites the data in the previous sets. 

0 0
replied on June 29, 2022 Show version history

Your function is written to run on every row of the collection.
Everything between
row 4:     $('.addressInput1 input').each(function () {
and
row 47:     });
is set-up to run on each one of the $('.addressInput1 input') fields.  So every time it triggers it is going to run on every one of the fields, not one specifically.

Could you provide a little more information regarding specifically when you want it to be triggered (example: when addressInput1 changes, run the API only on that row of the collection).

1 0
replied on June 29, 2022

Hmmmm.....it should trigger then the user start to type the address in the "From Address" field 

0 0
replied on June 29, 2022

Made a few edits to the code, just for testing purposes; the initial address pulls now pulls the address + coordinates on the same line, that works perfectly fine. 

 

I have a separate piece of code that pulls a portion of what is on the address line. It works, but I am having the same issue. Code that is causing the issue below. Also video (sorry for the bad quality) 

 

$(document).ready(function(){
  $('.travelInfoCollection').on('change', coordinateSearch);
  function coordinateSearch() {
    $('.addressInput1 input').change(function(){
      $('.addressInput1 input').each(function (){
        var strAddress1 = $(this).val();
        var regexLat = new RegExp("{A:}([^{]*){:}");
        var lat1 = strAddress1.match(regexLat);
        //alert(lat1[1]);
        $('ul.rpx .fromLat input').val(lat1[1]);
      });
    });
  }
});

 

Untitled.mp4 (4.29 MB)
0 0
replied on June 29, 2022

If anyone cares, got the latitude to pull correctly with the following code:

 

$(document).ready(function(){
  $('.travelInfoCollection').on('change','.addressInput1 input',function(){
    var strAddress1 = $(this).val();
    var latInput = $(this).parents('ul.rpx').find('.fromLat input');
    var regexLat = new RegExp("{A:}([^{]*){:}");
    var lat1 = strAddress1.match(regexLat);
    latInput.val(lat1[1]);
  });
});

It's not pretty, but gets the job done for now 

0 0
SELECTED ANSWER
replied on June 29, 2022

That's great!  Unlike the original code that was cycling through each one of the addressInput1 fields - your new code is only looking at the instance of addressInput1 that specifically was changed.

0 0
replied on July 6, 2022

Final code used:

 

$(document).ready(function(){
  $('.travelInfoCollection').on('blur', 'input', addressAutoComplete);
  function addressAutoComplete(){
      $('.addressInput1 input').each(function () {
        var objSet =  $(this);
        var latInput = $(this).parents('ul.rpx').find('.fromLat input');
        var longInput = $(this).parents('ul.rpx').find('.fromLong input');
        objSet.autocomplete({
          source: function (request, response) {
            $.ajax({
              url: "https://dev.virtualearth.net/REST/v1/Locations",
              dataType: "jsonp",
              data: {
                key: "<API KEY HERE>",
                q: request.term
              },
              jsonp: "jsonp",
              
              success: function (data) {
                var result = data.resourceSets[0];
                if (result) {
                  if (result.estimatedTotal > 0) {
                    response($.map(result.resources, function (item) {
                      return {
                        data: item,
                        label: item.name + ' (' + item.address.countryRegion + ')',
                        value: item.name 
                      }
                    }));
                  }
                }
              }
            });
          },
          minLength: 1,
          change: function (event, ui) {
            if (!ui.item)
              objSet.val('');
          },
          
          select: function (event, ui) {
           displaySelectedItem1(ui.item.data);          
          }
        });

        function displaySelectedItem1(item) {
          latInput.val(item.point.coordinates[0]);
          longInput.val(item.point.coordinates[1]);
        }
        //trigger change so that calculated fields are triggered. 
        $('.fromLat input').change();
        $('.fromLong input').change();
        $('.searchDistanceURL input').change();
        
      });
  }
});

 

1 0
replied on June 29, 2022

This line:   $('.travelInfoCollection').on('blur', 'input', addressAutoComplete);

Is basically saying to call your addressAutoComplete function any time the collection is blurred.  Which means it's triggering a lot.  It'll trigger on changes, when you click in the collection and then out of the collection, when you add rows to the collection, when you delete rows in the collection, etc.).

Something like this might work better:   $('.travelInfoCollection input').('change', addressAutoComplete);

That will trigger the function whenever any input field in the collection is changed.  That shouldn't be triggered by just blurring the field, or adding/deleting rows.

Another idea - I have some API calls that I do, that are triggered by button clicks - so it doesn't do trigger the API until the user has clicked the button.  Might not be ideal for your situation, but it's an idea.

1 0
replied on June 29, 2022

Hi Matthew, 

 

Thanks for that, updated the lines as advised

0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.