1

Sorry to post it, but I tried all solutions I found on the web. This seems to be a common problem but I just can't make it work. After a full day on it I give up. It must be a silly point, any vue.js guru will find the point in seconds. Any help will be appreciated.

The point : I receive some JSON and try to update my page with the received values, but the fields are null. jsonSettings.length is always 0.

I think I understand why: it's surely because the 'pointer' on the arrays doesn't change so vue.js doesn't detect the change of the content, or something similar, but I just can't make it work and it's driving me CRAZY.

My HTML :

<!DOCTYPE html>
<html>
<head>
    <title>List</title>
    <script src="/js/vue.min.js"></script>
    <script src="/js/axios.js"></script>
</head>
<body>
    <div id="app">
        Message : {{ message }} <BR>
        Length : {{ jsonSettings.length }} <BR>
        Typeof : {{ jsonSettings.typeof }} <BR>
        <button v-on:click="getData()">Load data</button>
        <button v-on:click="printData()">Print data</button>
    </div>
</body>
<script src="/javascripts/axios.js"></script>
</html>

My JavaScript:

var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!',
        // jsonSettings: [],
    },
    methods: {
        jsonSettings : function() {
            return (
                [
                    { id: 0, resume: 'test 0'},
                    { id: 1, resume: 'test 1'},
                    { id: 2, resume: 'test 2'}
                ]
            )
        },

        getData : function () {
            axios.get('/axios/LoadAxiosData')
                .then(function (response) {
                    this.jsonSettings = response.data;
                    this.message = "getData - I get objects : " + jsonSettings.length + " lines ";
                    this.$set('jsonSettings', response.data);
                    this.message = "getData - OK";

                })
                .catch(function (error) {
                    this.message = "getData - I get null";
                });
        },

        printData: function () {
            this.message =  "printData - jsonSettings.length  = [" + jsonSettings.length + "]";

            jsonSettings.map((item, i) => console.log('Index:', i, 'Id:', item.resume));

        }
    }
})

Sorry again, but I just can't make it work and I'm stuck in the middle of the river because of this silly point :-(

Bert
  • 80,741
  • 17
  • 199
  • 164
Gregoire Mulliez
  • 1,132
  • 12
  • 20
  • Possible duplicate of [Axios can't set data](https://stackoverflow.com/questions/40996344/axios-cant-set-data) – thanksd Aug 29 '17 at 20:51

2 Answers2

1

Incorrect this strikes again. Essentially, the this inside your axios callbacks is not a reference to the Vue. In order to make it point to the Vue you need to use an arrow function, or use bind or capture the correct this in a closure. Here, I'm using an arrow function.

getData : function () {
  axios.get('/axios/LoadAxiosData')
    .then(response => {
      this.jsonSettings = response.data;
      this.message = "getData - I get objects : " + jsonSettings.length + " lines ";

    })
    .catch(error =>  {
        this.message = "getData - I get null";
    });
},

See How to access the correct this inside a callback?

Also delete your jsonSettings method and add the data property back in.

data: {
    message: 'Hello Vue!',
    jsonSettings: [],
},

Working example. You'll see in the example that I cleaned up a couple other things.

Bert
  • 80,741
  • 17
  • 199
  • 164
  • Thanks Bert, it's working ! If I understand correctly it's a scope issue (this. jsonSettings in axios get "then" wasn't pointing on "Vue" jsonSettings), I will investigate the other solutions you provided, it's working but I don't understand why (I am a complete beginner in javascript and vue). Thank you very much again Bert – Gregoire Mulliez Jun 06 '17 at 07:08
  • @GregoireMulliez don't worry, it's a common error for people new to javascript and vue. Understanding `this` is one of the harder to understand concepts. – Bert Jun 06 '17 at 15:16
0

For next readers, the => method provided by Bert is working like a charm, case closed.

I post here the complete working code for further use, I hope it will help you in your research.

The HTML code page :

<!DOCTYPE html>
<html>
<head>
    <title>List</title>
    <script src="/js/vue.min.js"></script>
    <script src="/js/axios.js"></script>
</head>
<body>
    <div id="app">
        Message : {{ message }} <BR>
        Length : {{ jsonSettings.length }} <BR>
        <ul>
            <li v-for="setting in jsonSettings">
                {{ setting.resume }}
            </li>
        </ul>
        <button v-on:click="getData()">Load data</button>
        <button v-on:click="printData()">Print data</button>
    </div>
</body>
<script src="/javascripts/axios.js"></script>
</html>

the vue javascript :

var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!',
        jsonSettings: []
    },
    methods: {
        getData : function () {
            axios.get('/axios/LoadAxiosData')
                .then(response => {
                    this.jsonSettings = response.data;
                    this.message = "getData - I get objects : " + jsonSettings.length + " lines ";
                    this.$set('jsonSettings', response.data);
                })
                .catch(function (error) {
                    this.message = "getData - I get null";
                });
        },

        printData: function () {
            this.message =  "printData - jsonSettings.length  = [" + this.jsonSettings.length + "]";
            this.jsonSettings.map((item, i) => console.log('Index:', i, 'Id:', item.resume));

        }
    }
})

For the server code - don't forget to npm install --save axios and vue and add those lines in your router :

app.use('/js', express.static(__dirname + '/node_modules/vue/dist')); // redirect Vue.js
app.use('/js', express.static(__dirname + '/node_modules/axios/dist')); // redirect axios.js

I want to be abble to use and develop without any externale links / library so I add the libs axios, vue (and boostrap) using npm and add a link using express to the proper modules location

so the server code :

var express = require('express');
var router = express.Router();

// don't forget to change yur dbuser username, password and database name
const sequelize = new Sequelize('postgres://dbuser:password@localhost:5432/database');

const Testing = sequelize.define('testing', {
    resume: Sequelize.TEXT,
    description: Sequelize.TEXT,
    state: Sequelize.BOOLEAN
});

router.get('/', function(req, res, next) {
    res.render('axios', { testings: null });
});

router.get('/LoadAxiosData', function(req, res, next) {
    Testing.findAll({
        order: [ [ 'state' ] ]
    })
        .then (function(testings)   {
            res.json(testings);
        })
        .catch(function(error) {
            console.log("### Error ###" + error);
            res.send(null);
        });
});

// to create database structure - portgresql 
router.get('/init', function (req, res, next) {
    Testing.sync ({force:true});
    res.redirect('/');
});

module.exports = router;
Gregoire Mulliez
  • 1,132
  • 12
  • 20