Skip to content
Advertisement

How do I assign an array of objects to an empty array in a Vue component?

I am trying to write my first Laravel program that uses Vue components. I am using Laravel 8.x and Vue 2.x and running on Windows 10. I’m imitating a video that shows how to do it. Unfortunately, not everything he’s doing works for me. Some people here were very helpful to me yesterday in solving the problem I was having then but now I’ve got a new one that I can’t figure out.

He is doing a get request with Axios to read data previously put into a MySQL table in the Vue component. Axios returns a response that includes the data and then assigns it to an initialized empty array in the data() area of the component. He defines the empty array as follows:

todos: '',

The method that executes the Axios get looks like this:

getToDos() {
        debugger;
        axios.get('/todo')
        .then(function (res) {
            if (res.data.length == 0) console.log("Table is empty");
            else {
                this.todos = res.data
            }
            })
        .catch(function (error) {
            console.log(error);
            })
    },

As you can see, he is simply assigning all of res.data, which appears to be an array of objects, to the todos array in the data() area. When he executes the code, it works fine but he is using Laravel 7.x while I am using 8.x. When I try to execute this code, I get an error in the Chrome Debugger:

TypeError: this is undefined

which highlights the assignment statement (this.todos = res.data). I’m still new to Javascript and I’m not fluent with the idioms yet but it looks to me as if todos is being defined as an empty string and getting assigned an array of objects so I really expected that to fail when he executed it but it didn’t. Maybe this has something to do with him using Laravel 7.x??

Anyway, I did some researching and I tried a bunch of variations in this code but I always get the same error message when I’m assigning something to the todos variable, even if I define it as

todos: []

or

todos: new Array()

I’ve tried writing a for loop and pushing each Object from res.data into todos. Nothing works. Can someone kindly enlighten me on why his code works and why it doesn’t work for me? I simply want to put res.data where I can access it in my template so that I can display the relevant data.

Edit: Here is the entire component.

    <template>
    <div class="container">
        <form @submit.prevent="addTask"> 
            <div class="input-group mb-3 w-100">
                <input type="text" v-model="form.todo" class="form-control" placeholder="Enter new task" aria-label="Enter new task" aria-describedby="button-addon2">
                <div class="input-group-append">
                    <button class="btn btn-success" type="submit" id="button-addon2">Add new task</button>
                </div>
            </div>
        </form>
        <div class="w-25">
            <h1 class="text-white">...</h1>
            <div v-for="todo in todos" :key="todo.id" class="w-100 text-white">
                {{ todo.title }}
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                todos: '',

                form: new Form({
                    title: '',
                })

            } 
        },
        methods: {
            getToDos() {
                debugger;
                axios.get('/todo')
                .then(function (res) {
                    if (res.data.length == 0) console.log("Table is empty");
                    else {
                        this.todos = res.data
                        // var id = 0;
                        // var title = '';
                        // var completed = false;
                        // for (var ix=0; ix<res.data.length; ix++) {
                        //     id = res.data[ix].id;
                        //     title = res.data[ix].title;
                        //     completed = res.data[ix].completed;
                            // var oneToDo = new Object(res.data[ix]);
                            // this.todos.push(oneToDo);
                        // }   
                    }
                    })
                .catch(function (error) {
                    console.log(error);
                    })
            },
            addTask() {
                let data = new FormData();
                data.append('todo', this.form.todo);
                axios.post('/todo', data)
                .then(function (response) {
                    console.log(response);
                    this.form.reset;
                    this.getToDos();
                    })
                .catch(function (error) {
                    console.log(error);
                    })
            }
        },
        mounted() {
            console.log('ToDoComponent mounted.');
            this.getToDos();
        }
    }
</script>

<style lang="scss" scoped>
.container {
    padding-top: 5em;
}
</style>

Advertisement

Answer

The closure of this in function(){ //code } is the function itself. If you want to access the this of the object which you defined the function you will need to use arrow function as follow.

var obj = {
    getToDos() {
       // this here refer to obj
       axios.get('/todo')
        .then( res =>  {
           this.todos =  res.data
       })
    }

}

More information about closure in js: https://www.w3schools.com/js/js_function_closures.asp https://medium.com/@vmarchesin/javascript-arrow-functions-and-closures-4e53aa30b774

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement