1

I've successfully used fetch and displayed the data in the console. Problem is, the data doesn't look NEARLY as clean as examples I've looked at seem to be. I've been assigned (Udemy course) to extract certain information and make it so a user can enter a city name and produce the information relating to that city, but I can't find anything walking through extracting information from messy data.

Image of the console after fetch: Console post fetch()

I thought the querySelecter and insertAdjacentHTML scripts would help convert the data into something I can work with, but I feel like I've tried everything my JavaScript beginner mind can muster and nothing has worked yet.

Code:

const getDataButton = document.getElementById("get-data-button");
const dataContainer = document.getElementById("data-container");

getDataButton.addEventListener("click", () => {
    fetch("https://api.openweathermap.org/data/2.5/weather?lat=47.6&lon=-122.3&appid=etcetcetc")
      .then(response => response.json())
      .then(data => displayJson(data))
    //.then(response => response.text())
    //.then(data => displayText(data))


    displayJson = (json) => console.log(json);


    data.forEach(post => {
      let postData = document.querySelector('tr').insertAdjacentHTML("beforeend", markup);
      postData.innerHTML = `<h2>${post.title}</h2> <p>${post.body}</p>`;
      dataContainer.appendChild(postData);
    });
  })


  .catch(err => {
    console.log(err);
  })
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Weather</title>
</head>

<body>
  <label for="place">Enter a City Name:</label>
  <input type="text" id="place">
  <button id="get-data-button" type="submit">Submit</button>
  <div id="data-container"></div>
  <table id="weather">
    <tr>
      <th>City</th>
      <th>Temp</th>
      <th>Humidity</th>
      <th>Wind Speed</th>
    </tr>

  </table>
  <script src="weather.js"></script>
</body>

</html>

Any help is greatly appreciated!

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • `.catch` is a method for promise objects, but you call it on the return value of `addEventListener` which returns `undefined`. – trincot Aug 31 '23 at 20:34
  • What do you hope to get with `title` and `body`? There are no such members in the JSON you get in the response... What is the expected output you are aiming for? – trincot Aug 31 '23 at 20:41
  • @trincot - then I'm confused on what the question is because they're asking to convert the JSON into something they can work with. What other conversion would be needed? – devlin carnate Aug 31 '23 at 20:46
  • What is the purpose of `data-container`? What is supposed to get displayed there? – trincot Aug 31 '23 at 20:47
  • @trincot I'm hoping to get the data I pull to display in a table. At the moment I just made the headers and planned to come back to that once I have actual data to input if that makes sense. Also a good chuck of the code was provided by the instructor to work with (probably part of my confusion) so data.container was just part of what he had put in. – uncanny-vegan-taco Aug 31 '23 at 20:49
  • There are a number of issues here and I expect one could write an entire tutorial on how two take an object (or array of them) and churn out HTML. In fact, we have several questions about just that: [How to create an HTML table from an array of objects?](https://stackoverflow.com/q/72527457/215552), [Generating an HTML table from an array of objects](https://stackoverflow.com/q/61141898/215552). Are they going to match the data you're getting exactly? No, but it should be close enough to get you going... – Heretic Monkey Aug 31 '23 at 20:52
  • Does this answer your question? [How to create an HTML table from an array of objects?](https://stackoverflow.com/questions/72527457/how-to-create-an-html-table-from-an-array-of-objects) – Heretic Monkey Aug 31 '23 at 20:53
  • I think my biggest problem at the moment is that the data doesn't look like any array I've seen yet (been coding for a month). I'm used to seeing them output in a clean and numbered format, so I'm just not sure what to do with it as is. – uncanny-vegan-taco Aug 31 '23 at 20:57

1 Answers1

0

There are several issues here, including:

  • data.forEach executes too early. The then callbacks have not executed yet. You need to execute this as part of the displayJson function

  • data.forEach assumes the response is an array, but looking at the given URL, it returns a plain object, not an array.

  • .catch() is called on the return value of addEventListener(), but that doesn't return anything (undefined), not a promise. catch() is a method of promise objects.

  • insertAdjacentHTML() returns nothing (undefined), and so postData will be undefined and so the subsequent call of appendChild will not do what you want.

  • post.title and post.body access keys that don't exist in the response. The response has keys like wind, main, name, ... but not title or body.

  • displayJson is not declared with var, let or const and is thus defined as a global variable. It is better practice to perform explicit declarations.

  • data is referenced as if it is a variable that is available from the callback parameter used for a then argument. This is not true. You should use the argument you get passed into displayJson

Here is a rewrite of your code:

const getDataButton = document.getElementById("get-data-button");
const table = document.getElementById("weather");

function displayJson(data) {
    const row = table.insertRow();
    row.insertCell().textContent = data.name;
    // Convert to Celsius
    row.insertCell().textContent = +(data.main.temp - 273.15).toFixed(2); 
    row.insertCell().textContent = data.main.humidity;
    row.insertCell().textContent = data.wind.speed;
};

getDataButton.addEventListener("click", () => {
    fetch("https://api.openweathermap.org/data/2.5/weather?lat=47.6&lon=-122.3&appid=30967b695a09a50b12dd726193281aa5")
        .then(response => response.json())
        .then(displayJson);
});
td, th { border: 1px solid }
<button id="get-data-button" type="submit">Submit</button>
<div id="data-container"></div>
<table id="weather">
    <tr><th>City</th><th>Temp (C°)</th><th>Humidity</th><th>Wind Speed</th></tr>
</table>

Probably the next thing to do is to take the actual input from the user and adapt the URL accordingly.

trincot
  • 317,000
  • 35
  • 244
  • 286