Nadia  Medvid
Nadia Medvid

Reputation: 25

How to use value from select in fetch

I need to choose the city in Select and then insert it to the fetch to get weather forecast of the user selected city, but I got this message before I got a chance to choose something:

Uncaught ReferenceError: strUser is not defined:

document.querySelector(".city-select").onchange = () => {
    let strUser = document.querySelector(".city-select").value;
}

fetch(`'http://api.openweathermap.org/data/2.5/weather?q=${strUser}&appid=f3ab273b1163fcf008d6dce02f9e86e'`)
    .then(function (resp) { return resp.json() })
    .then(function (data) {
        document.querySelector('.package-name').textContent = data.name;
        document.querySelector('.temp').innerHTML = Math.round(data.main.temp - 273) + '°';
    })
    .catch(function () {
    });

Upvotes: 0

Views: 985

Answers (2)

Imran Rafiq Rather
Imran Rafiq Rather

Reputation: 8118

Why you are getting the error is because let keyword has block scope and cannot be accessed within your fetch();

Also, fetch() is asynchronous.

Best solution would be to wrap your fetch call inside a function and only once the strUser is available call it. Try this:

document.querySelector(".city-select").onchange = () => {
    let strUser = document.querySelector(".city-select").value;
    getDetails(strUser);
}


function getDetails(strUser){
  fetch(`'http://api.openweathermap.org/data/2.5/weather?q=${strUser}&appid=f3ab273b1163fcf008d6dce02f9e86e'`)
    .then(function (resp) { return resp.json() })
    .then(function (data) {
        document.querySelector('.package-name').textContent = data.name;
        document.querySelector('.temp').innerHTML = Math.round(data.main.temp - 273) + '°';
    })
    .catch(function () {
    });
}   

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1075337

Your strUser variable is scoped to the change event handler.

You seem to want to repeat the fetch whenever that value changes, so I'd suggest putting the fetch in a function you can then call any time you want to update the information it shows. For instance:

document.querySelector(".city-select").onchange = () => {
    let strUser = document.querySelector(".city-select").value;
    updateInfo(strUser);
};

function updateInfo(strUser) {
    fetch(`'http://api.openweathermap.org/data/2.5/weather?q=${strUser}&appid=f3ab273b1163fcf008d6d3ce02f9e86e'`)
        .then(function (resp) { return resp.json() })
        .then(function (data) {
            document.querySelector('.package-name').textContent = data.name;
            document.querySelector('.temp').innerHTML = Math.round(data.main.temp - 273) + '°';
        })
        .catch(function () {
            // Best to handle/report the error here
        });
}

Side note: You don't need to re-query the DOM to find the element the change happened on if you use a traditional function rather than an arrow function; you can use this within the function instead:

document.querySelector(".city-select").onchange = function() {
    let strUser = this.value;
    updateInfo(strUser);
};

Side note 2: Your code is falling prey to a bit of a footgun in the fetch API (I write about it here). fetch only rejects its promise on network errors, not HTTP errors, so your code may end up calling json when it's received a 500 or 404 error or similar. You have to do the check for HTTP success explicitly (which is why I always wrap fetch in a utility function):

fetch(`'http://api.openweathermap.org/data/2.5/weather?q=${strUser}&appid=f3ab273b1163fcf008d6d3ce02f9e86e'`)
    .then(function (resp) {
        if (!resp.ok) {                                   // ***
            throw new Error("HTTP error " + resp.status); // ***
        }                                                 // ***
        return resp.json();
    })
    .then(function (data) {
        document.querySelector('.package-name').textContent = data.name;
        document.querySelector('.temp').innerHTML = Math.round(data.main.temp - 273) + '°';
    })
    .catch(function () {
        // Best to handle/report the error here
    });

Upvotes: 2

Related Questions