Home > Mobile >  Why data returning from Laravel 9 api endpoint not showing in Vue UI?
Why data returning from Laravel 9 api endpoint not showing in Vue UI?

Time:08-26

I'm developing simple TodoList app using Laravle 9, VueJS 3, Vite bundler - all this built in tools when creating Laravel fresh installation.

In app user can make CRUD operations with TodoItem and all user data saved on server, so data preserved on page refresh.

Application almost finished, unless some strange bug: when I run app on local machine - all works perfectly, but when I deploy it on Heroku and open in browser - I see no todos in UI, although during installation some example todo rows already seeded in db.

I examined API - it returns data as expected:

[
    {
        "id": 67,
        "text": "Thing1",
        "is_done": false,
        "is_urgent": false,
        "created_at": "2022-08-24T09:16:37.000000Z",
        "updated_at": "2022-08-24T09:16:37.000000Z"
    },
    {
        "id": 68,
        "text": "Buy milk",
        "is_done": false,
        "is_urgent": false,
        "created_at": "2022-08-24T09:16:37.000000Z",
        "updated_at": "2022-08-24T09:16:37.000000Z"
    },
    {
        "id": 69,
        "text": "Thing2",
        "is_done": true,
        "is_urgent": false,
        "created_at": "2022-08-24T09:16:37.000000Z",
        "updated_at": "2022-08-24T09:16:37.000000Z"
    },
    {
        "id": 70,
        "text": "Thing3",
        "is_done": true,
        "is_urgent": false,
        "created_at": "2022-08-24T09:16:37.000000Z",
        "updated_at": "2022-08-24T09:16:37.000000Z"
    }
    
]

When I create new Todo in textbox request sends to server, and data saved on remote server - but on page refresh - I again get empty data in UI, althout i see in that data loaded

This is my App.vue

<template>

    <div  style="padding-left: 0 !important;">
        <h3><span >Simple</span> TodoList</h3>
    </div>

    <div >
        <div >

            <!-- Simple todos -->
            <div  style="border: 1px solid #ddd">

                <p>Todos ({{ simpleTodos.length }})</p>

                <ul>
                    <li :id="todo.id"
                        :key="todo.id"
                        :
                        v-for="todo in simpleTodos"
                        @click="contentVisible === todo.id ? contentVisible = false : contentVisible = todo.id">

                        {{ todo.text }}


                    </li>
                </ul>

                <input type="text" name="todo" id="todo.new" @keydown.enter="addTodo" placeholder="Type todo and press Enter" />
            </div>

            <!-- Urgent todos -->
            <div  style="border: 1px solid #ddd">

                <p>Todos <span :>({{  urgentTodos.length }})</span></p>

                <ul>
                    <li :id="todo.id"
                        :key="todo.id"
                        :
                        v-for="todo in urgentTodos"
                        @click="contentVisible === todo.id ? contentVisible = false : contentVisible = todo.id">

                        {{ todo.text }}

                       
                    </li>
                </ul>
            </div>

        </div>
    </div>
</template>

<script>

import {getAllTodos, createTodo, removeTodo, toggleTodoCompleteStatus, toggleTodoUrgentStatus} from '../services/TodoService'

export default {
    name: "App",

    data() {
        return {
            allTodos: [],
            contentVisible: false
        }
    },

    mounted() {
        this.getAllTodos();
    },

    computed: {

        simpleTodos() {
            return this.allTodos.filter(todo => todo['is_urgent'] === 0);
        },

        urgentTodos() {
            return this.allTodos.filter(todo => todo['is_urgent'] === 1);
        }
    },

    methods: {


        getAllTodos()
        {
            getAllTodos()
                .then(todos => {
                    console.log(todos)
                    this.allTodos = todos
                })
                .catch(err => {
                   alert('Error happened while fetching todos!');
                   console.error(err)
                });
        },


        addTodo(e)
        {
            // return if value is empty
            if(e.target.value.trim().length === 0)
                return false;

            const clientTodo = { text: e.target.value, is_done: 0, is_urgent: 0 }

            createTodo(clientTodo).then(({ todo }) => {
                this.allTodos.push(todo);
                e.target.value = "";
            });
        },



    }
}
</script>

<style scoped>

    .todo-item__link {
        cursor: pointer;
        position: relative;
    }

    .todo-item__link .text-primary {
        position: absolute;
        padding-left: 10px;
    }

    .todo-item__link:hover {
        text-decoration: underline;
    }
</style>

I tring to use Vue Debug Tools - it shows empty allTodos list. I don't unsderstand why this.getAllTodos() doesn't update state on mount

CodePudding user response:

The problem is the is_done and is_urgent properties are Booleans in your API resonse, but your component is incorrectly comparing them to 0 and 1:

export default {
  computed: {
    simpleTodos() {
      //return this.allTodos.filter(todo => todo['is_urgent'] === 0); ❌ Boolean is never a number

      return this.allTodos.filter(todo => todo['is_urgent'] === false); ✅
      // or
      return this.allTodos.filter(todo => !todo.is_urgent); ✅
    },

    urgentTodos() {
      //return this.allTodos.filter(todo => todo['is_urgent'] === 1); ❌ Boolean is never a number

      return this.allTodos.filter(todo => todo['is_urgent'] === true); ✅
      // or
      return this.allTodos.filter(todo => todo.is_urgent); ✅
    }
  },
  methods: {
    addTodo(e) {
      // const clientTodo = { text: e.target.value, is_done: 0, is_urgent: 0 } ❌ is_done and is_urgent should be Boolean

      const clientTodo = { text: e.target.value, is_done: false, is_urgent: false } ✅
    }
  }
}

demo

  • Related