Search code examples
vue.jsdata-bindingvuejs2v-modelvue-directives

Dynamically data doesn't update when changing v-model input value in Vuejs


I am building a weather app with this Weather API. I am trying to add an <input> field value that when it changes the city name, then updates the other values forecast.

I have created the <input> field which updates the city value & it should update the weather forecast accordingly. I know the v-model is working, however it doesn't change the data results. Only when I hard-code a different city in the Vue-instance the data updates the changes.

<template>
  <div class="home">
    <h1>{{ msg }}</h1>
    <p>A weather app built Vuejs & Open Weather App. Made by Manuel Abascal</p>
    <input type="text" v-model.lazy="currentWeather.name">
    <div class="forecast">
     <div v-if="this.currentWeather">
      <!-- Forecast stat values -->
      <h2>Right now:</h2>
      <div><strong>City:</strong> {{ currentCity }}</div>
      <div><strong>Longitude: </strong> {{ currentWeather.coord.lon }}</div>
      <div><strong>Latitude: </strong> {{ currentWeather.coord.lat }}</div>
      <div><strong>Weather condition </strong> {{ currentWeather.weather[0].description }}</div>
      <div><strong>Temperature Mid: </strong> {{  currentWeather.main.temp }} Farenheit</div>
      <div><strong>Temperature Max: </strong> {{  currentWeather.main.temp_max}} Farenheit</div>
      <div><strong>Temperature Min: </strong> {{  currentWeather.main.temp_min}} Farenheit</div>
      <div><strong>Humidity: </strong> {{  currentWeather.main.humidity }}%</div>
      <div><strong>Wind: </strong> {{  currentWeather.wind.speed }} mph</div>
     </div>
    </div>
  </div>
</template>

<script>
// import Axios
import axios from "axios"

export default {
  name: "Home",
  props: {
    msg: String,
  },
  data(){
    return {
      // current weather
      currentWeather: null,
      // current city
      currentCity: 'Montreal',
      // current country
      currentCountry: 'ca',
      unit: 'imperial'
    }
    this.$set(this.currentCity);
  },
  mounted(){
    // Make axios request to open weather api
    axios.get('https://api.openweathermap.org/data/2.5/weather?q='+this.currentCity+','+this.currentCountry+'&appid=fe435501a7f0d2f2172ccf5f139248f7&units='+this.unit+'')
    .then((response) => {
        // takes response object & stores it in currentWeather
        this.currentWeather = response.data

    })
    .catch(function (error) {
        // handle error
        console.log(error);
    })
  }
};
</script>

<style scoped lang="scss">

</style>

I am trying when I change to cities like Montreal, Toronto, Ottawa, Alberta, etc..it changes the forecast accordingly.


Solution

  • You have no event handler for currentCity changes. So your code will work on initial load (i.e on mounted) and changes to currentCity will not change any weather data.

    You need to add @change to the input and fetch new api data every time it changes.

    below is the sample code

    new Vue({
      el: '#app',
      data() {
        return {
          // current weather
          currentWeather: null,
          // current city
          currentCity: 'Montreal',
          // current country
          currentCountry: 'ca',
          unit: 'imperial'
        }
        this.$set(this.currentCity);
      },
      methods: {
        getWeather() {
          // Make axios request to open weather api
          fetch('https://api.openweathermap.org/data/2.5/weather?q=' + this.currentCity + ',' + this.currentCountry + '&appid=fe435501a7f0d2f2172ccf5f139248f7&units=' + this.unit + '')
            .then(res => res.json()).then(data => {
              // takes response object & stores it in currentWeather
              this.currentWeather = data;
    
            })
            .catch(function(error) {
              // handle error
              console.log(error);
            })
        }
      },
      mounted() {
        this.getWeather();
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
    <div id="app">
      <div class="home">
        <p>A weather app built Vuejs & Open Weather App. Made by Manuel Abascal</p>
        Search: <input type="text" v-model.lazy="currentCity" @change="getWeather">
        <div class="forecast" v-if="currentWeather && currentWeather.cod == 200">
          <!-- Forecast stat values -->
          <h2>Right now:</h2>
          <div><strong>City:</strong> {{ currentWeather.name }}</div>
          <div><strong>Longitude: </strong> {{ currentWeather.coord.lon }}</div>
          <div><strong>Latitude: </strong> {{ currentWeather.coord.lat }}</div>
          <div><strong>Weather condition </strong> {{ currentWeather.weather[0].description }}</div>
          <div><strong>Temperature Mid: </strong> {{ currentWeather.main.temp }} Farenheit</div>
          <div><strong>Temperature Max: </strong> {{ currentWeather.main.temp_max}} Farenheit</div>
          <div><strong>Temperature Min: </strong> {{ currentWeather.main.temp_min}} Farenheit</div>
          <div><strong>Humidity: </strong> {{ currentWeather.main.humidity }}%</div>
          <div><strong>Wind: </strong> {{ currentWeather.wind.speed }} mph</div>
        </div>
        <div v-else>
          "{{ currentCity }}" is not found
        </div>
      </div>
    </div>