Search code examples
javascriptjsonuser-inputjson-query

How to update JSON query / data after new user input?


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>


Solution

  • 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">&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>