I'm creating a weather dashboard that updates every 5 seconds. I would like the user to be able to change the target city, and have the dashboard update with the new data. Problem is every time they input a new city, the previous data stays and it seems to be looping through all the inputs the user has made so far.
I would like the data to be updated after the user inputs a new city, rather than added. This is my code:
window.onload = function() {
const api_key = "c7eedc2fa8594d69aa6122025212904";
const inputCity = document.getElementById("inputCity");
const getCity = document.querySelector("form");
getCity.addEventListener("submit", e => {
// Prevent the form from submission
e.preventDefault();
var inputVal = inputCity.value;
var api_url = "http://api.weatherapi.com/v1/forecast.json?key=" + api_key + "&q=" + inputVal + "&days=3&aqi=no&alerts=no";
// Get the dataset
function refreshData() {
fetch(api_url).then(response => {
response.json().then(json => {
var dataset = json;
var output = formatResponse(dataset);
})
// Catch error - for example, the user doesn't input a valid city / postcode / country
.catch(error => console.log("not ok")); // TO BE IMPROVED
})
}
refreshData(); // Display the dashboard immediately
setInterval(refreshData, 5000); // And then refresh the dashboard every X milliseconds
});
function formatResponse(dataset) {
console.log(dataset);
// Current temp
var currentTemp = [dataset.current.temp_c];
console.log(currentTemp);
document.getElementById("currentTempDsp").innerHTML = currentTemp + "°";
// Current state icon
var currentIcon = [dataset.current.condition.icon];
console.log(currentIcon);
document.getElementById("iconDsp").src = "http://" + currentIcon;
// Current state text
var currentText = [dataset.current.condition.text];
console.log(currentText[0]);
document.getElementById("currentStateDsp").innerHTML = currentText;
}
}
<form id="getCity" class="search">
<label id="labelCity">Search for a city...</label></br>
<input type="text" id="inputCity" class="inputCity" placeholder="Type city name here...">
<button id="submitCity" type="submit" class="submitCity"><i class="fas fa-search"></i>Submit</button>
</form>
<div class="state">
<h2 id="currentTempDsp"></h2>
<img id="iconDsp"/>
<span id="currentStateDsp"></span>
</div>
</div>
</div>
When you create an interval using setInterval()
it continues to execute until the page is reloaded, navigated away from, or explicitly cleared using clearInterval()
. Simply setting more intervals will not stop any previous ones from firing.
Use a globally-scoped variable to store the return value of setInterval()
- check if it's set in the beginning of your submit event handler and clear it if it is.
A simplified example of how you could get this done:
const locations = [{
temp: 73,
conditions: 'Sunny'
}, {
temp: 22,
conditions: 'Mostly Cloudy'
}];
var currentInterval = null;
const updateTemp = locationData => {
document.querySelector(".number").innerText = locationData.temp;
document.querySelector(".conditions").innerText = locationData.conditions;
console.log(`updated interface with temperature (${locationData.temp}) and conditions (${locationData.conditions}) data`);
}
[...document.querySelectorAll('.add-location')].forEach(button => {
button.addEventListener('click', (e) => {
// clear the interval
if (currentInterval) {
clearInterval(currentInterval);
currentInterval = null;
console.log('cleared currentInterval');
}
updateTemp(locations[parseInt(e.srcElement.dataset.loc)]);
currentInterval = setInterval(function () {
updateTemp(locations[parseInt(e.srcElement.dataset.loc)]);
}, 2500);
});
});
* {
font-family: sans-serif;
}
.temp {
font-size: 2em;
}
.conditions {
font-style: italic;
}
<div class="temp">
<span class="number">--</span>
<span class="deg">°</span>
</div>
<div class="conditions">--</div>
<div>
<button class="add-location" data-loc="0">Add location 0</button>
<button class="add-location" data-loc="1">Add location 1</button>
</div>