1

I'm expanding my knowledge learning VueJs, and for learning reasons, I am trying to use axios library to get JSON information. The problem is displaying an object in HTML. Printing everything in the console works fine, except doing it HTML.

When I load a page, it displays nothing, while in the console it shows all results.

HTML file:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <link rel="stylesheet" href="style.css">
    <script src="https://unpkg.com/vue"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <title>VueJs</title>
  </head>
  <body>
    <div class="innerBody" id="app">
        <p style="width: 100%; height: 40px; background: gray;">{{getDescription}}</p>
    </div>
    <script src="app.js"></script>
  </body>
</html>

JS file:

new Vue({
    el: '#app',
    data:{
        dataReceived: [],
        errorReceived: [],
        description: '',
    },
    methods: {
        getJson: function(city){
            axios.get('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22'+city+'%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys')
            .then(function (response) {
                dataReceived = response;
                console.log(dataReceived);
                return dataReceived;
            })
            .catch(function (error) {
                errorReceived = error;
                console.log(errorReceived);
                return errorReceived;
            });
         },
        getDescription: function(){
            description = dataReceived.data.query.results.channel.title;
            console.log(description);
            return description;
        }
    },
    beforeMount(){
        this.getJson('boston');
    }
});

Thank you in advance.

Aivaras
  • 35
  • 8

3 Answers3

5

There are a few problems with your code...

  • Your response handlers are not setting the data fields of your Vue instance. For instance, in the following code. dataReceived does not refer to dataReceived of your Vue object, which would require this.dataReceived.

    axios.get('...')
            .then(function (response) {
                dataReceived = response; // <-- should be: this.dataReceived
                console.log(dataReceived);
                return dataReceived;
            })
    

    You can use an ES2015 arrow-function to bind this to your Vue instance, then call this.dataReceived = response.

    axios.get('...')
            .then((response) => {
                this.dataReceived = response;
                console.log(dataReceived);
            })
    
  • Your template attempts to bind the getDescription function to the text content of a <div> with {{getDescription}}, but the correct syntax is {{getDescription()}} (note the parentheses).

    <div id="app">{{getDescription()}}</div>
    

    However, since the data used in getDescription is not available until the AJAX response returns, the binding should actually be something that gets updated by the newly received data. For instance, this binding could be a data field (e.g., named title) that is set by the AJAX response handler.

    new Vue({
      ...
    
      data() {
        return {
          dataReceived: {},
          title: ''
        }
      },
    
      methods: {
        getsJon() {
          axios.get('...')
            .then((response) => {
              this.dataReceived = response;
              this.title = parseTitle(this.dataReceived);
            });
        },
    
        parseTitle(data) {
          return /* ... */;
        }
      }
    });
    
    // HTML
    <div id="app">{{title}}</div>
    

demo

tony19
  • 125,647
  • 18
  • 229
  • 307
1

Change your binding to {{dataReceived}} and update your Vue instance like this

new Vue({
  el: "#app",
  data: {
    dataReceived: [],
    errorReceived: [],
    description: ""
  },
  methods: {
    getJson: function(city) {
      axios
        .get(
          "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22" +
            city +
            "%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"
        )
        .then(response => {
          this.dataReceived = response;
          console.log(this.dataReceived);
        })
        .catch(error => {
          this.errorReceived = error;
          console.log(this.errorReceived);
        });
    },
    getDescription: function() {
      this.description = this.dataReceived.data.query.results.channel.title;
      console.log(this.description);
    }
  },
  mounted: function() {
    this.getJson("boston");
  }
});

As the other responses noted, your variables in Vue are always children of a Vue instance, and should be set as such, using this.varName. Additionally, binding to the response of an async call will just give you the immediate return, which would (I believe) be a promise. Welcome to Vue, it's awesome!

edit: my use of mounted instead of beforeMount was just a personal choice as I was writing this, it should still work.

kidCoder
  • 354
  • 4
  • 17
0

To access properties in the data option, you need to use the this keyword, similar to how you accessed the getJson method.

For instance, to access the dataReceived variable in the .then of your AJAX call, you will need to adjust the following:

axios.get('your-url')
.then(function (response) {
    this.dataReceived = response;
    console.log(this.dataReceived);
    return this.dataReceived;
})

Use this to access any other of a components options (data values, computed values, methods, etc.)

Dominic Serrano
  • 124
  • 1
  • 5
  • https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback – Bert Oct 31 '17 at 23:00
  • Thanks for the answer, but after adding "this", it still is not displaying values on HTML. – Aivaras Oct 31 '17 at 23:06
  • you'll have to update your `then(function(response){})` to `then((response)=>{}) ` because otherwise `this` is no longer your Vue instance – kidCoder Oct 31 '17 at 23:09