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

Manuel Abascal picture Manuel Abascal · Jun 11, 2019 · Viewed 13.4k times · Source

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.

Answer

Ja9ad335h picture Ja9ad335h · Jun 11, 2019

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>