1

Background:

I am working on a mini project learning how to use AJAX via vanilla JavaScript with a JSON file. I am aware I can use Jquery but I am learning the long way and Jquery will be next.

Goal:

My goal is to be able to type in a city and once I click the button it will render the current weather for the city I typed in.

Problem:

I cannot figure out and am looking for guidance on how to essentially take the value and attach it to a key and render all the data I am seeking. My thought process is to bring in the input value and compare it to the name key and if they are a match render the results. I just can't wrap my head around how that could look in code so any guidance would be greatly appreciated.

What I have:

So far I am able to render what I want by hard-coding with the following file:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <title>Ajax3 - JSON(external api practice) File</title>
</head>
<body>
   <input id="city">
   <button id="button">Get Weather</button>
   <br><br>
   <h1>Weather</h1>
   <div id='weather'></div>
   <script>
           // Create an event listener
           document.getElementById('button').addEventListener('click', loadWeather);
           function loadWeather(){
               // console.log(city);
               let xhr = new XMLHttpRequest();
               xhr.open('GET', 'weather.json', true);
               xhr.onload = function(){
                   let city = document.getElementById('city').value;
                   // let keys = Object.keys(weather);
                   if(this.status == 200){
                       let weatherTest = JSON.parse(this.responseText);
                       let result = '';
                   //   weather.forEach((item, index) =>{
                       result += '<ul>'+
                           '<li>City: '+JSON.stringify(weatherTest[1].name )+ '</li>' +
                           '<li>Weather: '+JSON.stringify(weatherTest[1].weather[0].description )+ '</li>' +
                           '<li>Latitude: '+JSON.stringify(weatherTest[1].coord.lat )+ '</li>' +
                           '<li>Longitude: '+JSON.stringify(weatherTest[1].coord.lon )+ '</li>' +
                           '</ul>';
                           document.getElementById('weather').innerHTML = result;
                   //   })
                   }
               }
               xhr.send();
           }
           //HTTP statuses
           // 200: 'Ok'
           // 403: 'Forbidden'
           // 404: 'Not Found'
   </script>
</body>
</html>

Here is the JSON file data I am working with:

[{
   "coord":{
      "lon":-62.08,
      "lat":-31.43
   },
   "sys":{
      "message":0.3897,
      "country":"AR",
      "sunrise":1428575101,
      "sunset":1428616476
   },
   "weather":[
      {
         "id":802,
         "main":"Clouds",
         "description":"scattered clouds",
         "icon":"03d"
      }
   ],
   "base":"stations",
   "main":{
      "temp":303.364,
      "temp_min":303.364,
      "temp_max":303.364,
      "pressure":1015.65,
      "sea_level":1026.91,
      "grnd_level":1015.65,
      "humidity":42
   },
   "wind":{
      "speed":2.85,
      "deg":32.0037
   },
   "clouds":{
      "all":44
   },
   "dt":1428614645,
   "id":3837675,
   "name":"San Francisco",
   "cod":200
 },
{
   "coord":{
      "lon":-87.65,
      "lat":41.85
   },
   "sys":{
      "message":0.014,
      "country":"US",
      "sunrise":1428578344,
      "sunset":1428625502
   },
   "weather":[
      {
         "id":501,
         "main":"Rain",
         "description":"moderate rain",
         "icon":"10d"
      }
   ],
   "base":"stations",
   "main":{
      "temp":286.264,
      "temp_min":286.264,
      "temp_max":286.264,
      "pressure":991.9,
      "sea_level":1013.82,
      "grnd_level":991.9,
      "humidity":76
   },
   "wind":{
      "speed":8.25,
      "deg":202.004
   },
   "clouds":{
      "all":92
   },
   "rain":{
      "3h":4.61
   },
   "dt":1428615189,
   "id":4887398,
   "name":"Chicago",
   "cod":200
 }
]

3 Answers 3

1

As Todd R said, you just have to find the array element you actually want before accessing the properties. You also don't need JSON.stringify as the values are already strings or numbers and can be put straight into the HTML. Wrapping them in a stringify call will result in quotes being added to the string values eg.

<li>City: "San Francisco"</li>

Example code:

xhr.onload = function(){
    const city = document.getElementById('city').value;
    if(this.status == 200){
        let cityWeathers;
        try {
            cityWeathers = JSON.parse(this.responseText);
        } catch (e) {
            // JSON not valid, show error message
        }
        const cityWeather = Array.isArray(cityWeathers) && cityWeathers.find((obj)=>obj.name === city);
        if (cityWeather) {
            const result = `<ul><li>City: ${cityWeather.name}</li>` +
                `<li>Weather: ${cityWeather.weather[0].description}</li>` + 
                `<li>Latitude: ${cityWeather.coord.lat}</li>` +
                `<li>Longitude: ${cityWeather.coord.lon}</li></ul>`;

            document.getElementById('weather').innerHTML = result
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

You're almost there. Where your "forEach" comment starts, go through weatherTest to "find" (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) the element that matches "city". Then use the element you return from "find" to build "result".

I hope that helps!

Comments

1

Here is a slightly different demo, showing the use of fetch() as a new Vanilla Javascript way of doing Ajax:

I only get the data once (at load time and then scan the array for a pattern that matches the city. This is bound to the keyup event of the input field, making the button obsolete.

var data, ct=document.querySelector('#city'), wt=document.querySelector('#weather');
fetch('https://jsonplaceholder.typicode.com/users')
  .then(function(r){r.json().then(function(da){data=da;
  document.querySelector('#all').innerHTML=data.map(function(v){return v.address.city}).join(', ');});
})

ct.addEventListener('keyup',function(){
 wt.innerHTML='';
 var i,n=data.length, rx=new RegExp(ct.value,'i');
 for (i=0;i<n;i++) if (rx.test(data[i].address.city)) {
   wt.innerHTML=data[i].address.city+': '+data[i].address.zipcode 
 }
});
<input id="city"><br>
<div id="all"></div>
<h1>City and zip code</h1>
<div id='weather'></div>

Comments

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.