Arcturus
Arcturus

Reputation: 53

How to get Mapbox Geocoder result place/country text names into a JavaScript function?

When the Mapbox geocoder returns a search result, I need to get the city(place name) and country name text and put them into a text field on the web page.

This returns the data to the console.

<script>
geocoder.on('results', function(results) {
   console.log(results);
})
</script>

A geocoder search for New york returns this GeoJSON object data. I need to get the country text data when a search result is returned and update a text field on the web page with the country name text.

<script>
features: Array(5)
0:
bbox: (4) [-74.2590879797556, 40.477399, -73.7008392055224, 40.917576401307]
center: (2) [-73.9808, 40.7648]
context: Array(2)
0: {id: "region.14044236392855570", short_code: "US-NY", wikidata: "Q1384", text_en-GB: "New York", language_en-GB: "en", …}
1:
id: "country.9053006287256050"
language: "en"
language_en-GB: "en"
short_code: "us"
text: "United States of America"
text_en-GB: "United States of America"
wikidata: "Q30"
__proto__: Object
length: 2
__proto__: Array(0)
geometry: {type: "Point", coordinates: Array(2)}
id: "place.15278078705964500"
language: "en"
language_en-GB: "en"
matching_place_name: "New York, New York, United States of America"
matching_text: "New York"
place_name: "New York City, New York, United States of America"
place_name_en-GB: "New York City, New York, United States of America"
place_type: ["place"]
properties: {wikidata: "Q60"}
relevance: 1
text: "New York City"
text_en-GB: "New York City"
type: "Feature"
__proto__: Object
</script>

The below code updates the text field. However, not with the actual data from the above data. How do I query/access the actual result data after every search to update the text field?

<script>
//listen for a search result
document.querySelector('.mapboxgl-ctrl-geocoder--input').addEventListener('change', titleTest);

function titleTest() {

var countryName = {
  id: "country.9053006287256050",
  language: "en",
  language_enGB: "en",
  short_code: "us",
  text: "United States of America",
  text_enGB: "United States of America",
  wikidata: "Q30"
}

  //update the input field
document.getElementById('titleinput').value = countryName.text.toUpperCase(); 
  //add to map
document.getElementById("map_title").innerHTML = countryName.text.toUpperCase();

</script>

The below line returns the value for 'place_name: "New York City, New York, United States of America"'

<script>
 let str = document.querySelector('.mapboxgl-ctrl-geocoder--input').value;
</script>

Let's try it in the script below..

<script>
// listen for a search
document.querySelector('.mapboxgl-ctrl-geocoder--input').addEventListener('change', updateTitle);

function updateTitle() {

 //get the text value for place
 let str = document.querySelector('.mapboxgl-ctrl-geocoder--input').value;

 //split the string
 let countryName = str.split(", ");

 //loop over array items  
 for(var i = 0; i < countryName.length; i++)
{
   console.log(countryName[i]);
}

  //update the input field
  document.getElementById('titleinput').value = countryName[1].toUpperCase();
 //add to map
  document.getElementById("map_title").innerHTML = countryName[1].toUpperCase();
</script>

The above code gets me the mapbox suggestion [place_name] as a string ("New York City, New York, United States of America"), which I then split to a list, and iterate over. It works well for place/city as this array position is always first [0]. However, it doesn't work well for getting the country name, which isn't always in the same position in the string, or the list. For example, if I set the countryName array value to [1] and search for 'London', the second item is 'Greater London', 'England' was [2] and 'United Kingdom' was [3], whereas if I search for 'Paris', [1] gives me 'France'.

I need to get the country name text when the geocoder returns a result so I can add it to the text field. How do I get the country name text from the object after every search result? Does anyone know?

Upvotes: 4

Views: 3177

Answers (3)

RafalM
RafalM

Reputation: 23

Maybe that way will help you, that is how I resolved it. Note that you can do if-else-if instead of several if's as I did. You could even use switch if you wish so.

    geocoder.on('result', (e) => {
      for(let i=0; i < e.result.context.length; i++) {
        if(e.result.context[i].id.includes('postcode')) {
          this.form.postcode = e.result.context[i].text;
        }
        if(e.result.context[i].id.includes('locality')) {
          this.form.line_2 = e.result.context[i].text;
        }
        if(e.result.context[i].id.includes('place')) {
          this.form.city = e.result.context[i].text;
        }
        if(e.result.context[i].id.includes('district')) {
          this.form.county = e.result.context[i].text;
        }
        if(e.result.context[i].id.includes('country')) {
          this.form.country = e.result.context[i].text;
        }
      }
      // First line of address
      if(e.result.text || e.result.address) {
        this.form.line_1 = (e.result.address ? e.result.address + ' ' : '') + (e.result.text ? e.result.text : '');
      }
      // Full Address
      if(e.result.place_name) {
        this.form.full_address = e.result.place_name;
      }
      // Coordinates
      if(e.result.center) {
        this.form.longitude = e.result.center[0];
        this.form.latitude = e.result.center[1];
      }
    });

Upvotes: 1

idirsun
idirsun

Reputation: 604

  geocoder.on("result", (e) => {
    function getAddressByType(value, index, array) {
      if (value.id.match(/country.*/)) {
       console.log(value.text)
      } else if (value.id.match(/region.*/)) {
       console.log(value.text)
      } else if (value.id.match(/postcode.*/)) {
       console.log(value.text)
      } else if (value.id.match(/district.*/)) {
       console.log(value.text)
      } else if (value.id.match(/place.*/)) {
          console.log(value.text)
      } else if (value.id.match(/neighborhood.*/)) {
            console.log(value.text)
      } else if (value.id.match(/address.*/)) {
            console.log(value.text)
      } else if (value.id.match(/poi.*/)) {
       console.log(value.text)
      }
    }
    e.result.context.forEach(getAddressByType);
    console.log(JSON.stringify(e))
  });

note : "results" and "result" return different data. This is how I fetch all data under the context of "result" function. I loop the e.result.context then use a function to access the object to make sure I can use all object return on that array.

Upvotes: 3

chillinOutMaxin
chillinOutMaxin

Reputation: 182

Take the the Json object a return the string you are looking for. You can do a split function on this string to get all the values individually like so.

var listOfNames = obj.place_name.split(", ");
ListOfNames[0] = "New York City" 
ListOfNames[1] = "New York"
ListOfNames[2] = "United States"

Upvotes: 0

Related Questions