1

I want to create a simple weather report website using Vue.js, I just learned this framework and had accessed public data before. But this time I am stuck.

There are two versions of methods I have tried to get data.

var app = new Vue({
  el: "#weather",
  data: {
    city: '',
    weather:[],
    date: new Date().toDateString(),
    greeting:''

  },

  methods: {
  
  //method 1
    getData: function () {
      var city = this.city
        $.getJSON("http://api.openweathermap.org/data/2.5/weather?q=" + city + "&units=metric&lang=en&appid=a495404234abce9b5830b1e8d20e90a6", 
        function (data) {
          console.log(data)
        });

    },
    
   //method 2
    getData: function () {
      $("#search").keypress(function (e) {
        if (e.which == 13) {
          var city = $("#search").val();
          if (city != " ") {
            var url = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "&units=metric&lang=en&appid=a495404234abce9b5830b1e8d20e90a6";

            console.log(url);
            
          }
          $.getJSON(url, function (data) {
              this.weather = data.weather;
            console.log(data);
            this.returnGreeting();
            
          })
        }

      })
    },

    

    }

    
  }
});
<div class="container" id="weather">
    <h1>Weather Pro</h1>
    <div class="float-left"><h2>{{date}}</h2></div>
    <div class="float-right" ><h3 id="time"></h3></div>
    <p>{{greeting}}</p>

    <div class="input-group">
        <form>
          <input v-model="city" class='searchbar transparent' id='search' type='text' placeholder='      enter city' />
          
          <input id='button' @click="getData" type="button" value='GO' />
          
        </form>
    </div>

    {{city}}
    <div class="panel">

      <div class="panel-body" v-for="d in data">

        <p>
          {{data}}
        </p>
      </div>
      <ul class="list-group list-group-flush">
        <!-- <li class="list-group-item">{{data.weather[0].main}}</li>
        <li class="list-group-item">{{data.weather[0].description}}</li> -->
        
      </ul>
    
    </div>
  </div>
  
  <!-- vue -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <!-- jQuery library -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

I got an error :

[Vue warn]: Property or method "data" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

tony19
  • 125,647
  • 18
  • 229
  • 307
Tracy chan
  • 141
  • 1
  • 9
  • 1
    @zero298, only for components, the issue here is that `data.data` does not exist – Daniel Jun 06 '18 at 20:20
  • https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback – Bert Jun 06 '18 at 20:53

3 Answers3

1

Consider data to be your model. Don't reference data directly in your view, reference properties that are on the model instead.

So instead of <div>{{data.city}}</div> use <div>{{city}}</div>

var app = new Vue({
  el: "#weather",
  data() {
    return {
      city: '',
      weather: [],
      date: new Date().toDateString(),
      greeting: ''
    };
  },
  methods: {
    getData() {
      fetch("http://api.openweathermap.org/data/2.5/weather?q=" + this.city + "&units=metric&lang=en&appid=a495404234abce9b5830b1e8d20e90a6")
        .then(res => res.json())
        .then(data => {
          this.weather = data.weather;
        });
    }
  }
});
<div class="container" id="weather">
  <h1>Weather Pro</h1>
  <div class="float-left">
    <h2>{{date}}</h2>
  </div>
  <div class="float-right">
    <h3 id="time"></h3>
  </div>
  <p>{{greeting}}</p>
  <div class="input-group">
    <form>
      <input v-model="city" class='searchbar transparent' id='search' type='text' placeholder='      enter city' />

      <input id='button' @click="getData" type="button" value='GO' />

    </form>
  </div>

  {{city}}
  <div class="panel">
    <div class="panel-body" v-for="d in weather">
      <p>
        {{d}}
      </p>
    </div>
    <ul class="list-group list-group-flush"></ul>
  </div>
</div>

<!-- vue -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
zero298
  • 25,467
  • 10
  • 75
  • 100
0

looks like zero beat me to it, but here's a version using jquery call

the issue is, as mentioned in comment, that data.data is not defined. so define data inside data, and assign result to this.data. However, because it's inside a function and the scope changes, you need to store scope using var that = this and use that.data = data to assign result

dom:

<div class="container" id="weather">
  <h1>Weather Pro</h1>
  <div class="float-left"><h2>{{date}}</h2></div>
  <div class="float-right" ><h3 id="time"></h3></div>
  <p>{{greeting}}</p>

  <div class="input-group">
    <form>
      <input v-model="city" class='searchbar transparent' id='search' type='text' placeholder='      enter city' />

      <input id='button' @click="getData" type="button" value='GO' />

    </form>
  </div>

  {{city}}
  <div class="panel">

    <div class="panel-body" v-for="d in data">
      <p>
        {{d}}
      </p>
    </div>
    <ul class="list-group list-group-flush">
    </ul>

  </div>
</div>

<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Script:

var app = new Vue({
  el: "#weather",
  data: {
    city: '',
    weather:[],
    date: new Date().toDateString(),
    greeting:'',
    data: null,

  },

  methods: {
    //method 1
    getData: function () {
      var that = this;
      var city = this.city
      console.log('getData')
      $.getJSON("https://api.openweathermap.org/data/2.5/weather?q=" + city + "&units=metric&lang=en&appid=a495404234abce9b5830b1e8d20e90a6", 
                function (data) {
        console.log(data)
        that.data = data;
      });

    },
  }
});

Here is an example fiddle.

Bert
  • 80,741
  • 17
  • 199
  • 164
Daniel
  • 34,125
  • 17
  • 102
  • 150
0

I found out what caused the issues:

  1. I need to define data in data, as I reference data directly in my html page, but this is optional.
  2. Turns out there is a slim jQuery version from bootstrap that overrides the min jQuery. And $.getJSON() needs min jQuery.
Tracy chan
  • 141
  • 1
  • 9