0
votes

I have a problem when trying to insert the response of an API call (I am using axios) into a vue data table. If I manually write an html table like this:

<table style="width:100%">
            <tr>
                <th v-for="(item, n) in headers" v-bind:key="n">{{item.text}}</th>
            </tr>
            <tr v-for="(item, n) in info" v-bind:key="n">
                <td>{{ item.code }}</td>
                <td>{{ item.symbol }}</td>
                <td>{{ item.rate }}</td>
                <td>{{ item.description }}</td>
                <td>{{ item.rate_float }}</td>
            </tr>
        </table>

the code works and displays some data. But when I try to use the Vuetify data table like this:

<v-data-table
                app
                :headers="headers"
                :items="info"
                class="elevation-2"
        >
            <template v-slot:items="props">
                <td>{{ props.item.code }}</td>
                <td>{{ props.item.symbol }}</td>
                <td>{{ props.item.rate }}</td>
                <td>{{ props.item.description }}</td>
                <td>{{ props.item.rate_float }}</td>
            </template>
        </v-data-table>

it gives me the following warning:

webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:620 [Vue warn]: Invalid prop: type check failed for prop "items". Expected Array, got Object 

found in

---> <VDataTable>
       <ApiExample> at src/views/ApiExample.vue
         <VContent>
           <VApp>
             <App> at src/App.vue
               <Root>

Leading to this error:

webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:1887 TypeError: this.items.map is not a function
    at VueComponent.items (webpack-internal:///./node_modules/vuetify/dist/vuetify.js:21511)
    at Watcher.run (webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:4556)
    at flushSchedulerQueue (webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:4298)
    at Array.eval (webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:1979)
    at flushCallbacks (webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:1905)

The application works if instead of trying to diplay the dynamic data I try to display a statically defined object ("staticitems"). In my opinion the problem is that the data table is expecting an array but instead it finds a Promise so it crashes. Below is the full code for the application .

<template>
    <v-container fluid>
        <table style="width:100%">
            <tr>
                <th v-for="(item, n) in headers" v-bind:key="n">{{item.text}}</th>
            </tr>
            <tr v-for="(item, n) in info" v-bind:key="n">
                <td>{{ item.code }}</td>
                <td>{{ item.symbol }}</td>
                <td>{{ item.rate }}</td>
                <td>{{ item.description }}</td>
                <td>{{ item.rate_float }}</td>
            </tr>
        </table>
        <v-data-table
                app
                :headers="headers"
                :items="info"
                class="elevation-2"
        >
            <template v-slot:items="props">
                <td>{{ props.item.code }}</td>
                <td>{{ props.item.symbol }}</td>
                <td>{{ props.item.rate }}</td>
                <td>{{ props.item.description }}</td>
                <td>{{ props.item.rate_float }}</td>
            </template>
        </v-data-table>
    </v-container>
</template>

<script>
    import axios from 'axios'

    export default {
        name: "ApiExample",
        data() {
            return {
                info: [],
                info2: [],
                headers: [
                    {text: 'code', value: 'code'},
                    {text: 'symbol', value: 'symbol'},
                    {text: 'rate', value: 'rate'},
                    {text: 'description', value: 'description'},
                    {text: 'rate_float', value: 'rate_float'},
                ],
                staticitems: [
                    {
                        code: "USD",
                        symbol: "$",
                        rate: "5,247.0417",
                        description: "United States Dollar",
                        rate_float: "5247.0417"
                    }
                ]
            }
        },
        mounted() {
            axios
                .get('https://api.coindesk.com/v1/bpi/currentprice.json')
                .then(response => (this.info = response.data.bpi))
                .catch(error => console.error(error))
        }
    }
</script>

<style scoped>

</style>

1
Give us a sample of your data please that actually come back from the api. - Jeremy Walters
The api is public you can get the response at this link link - TheKrm95
bpi is an object. Is should be an array. - Jeremy Walters
yeah you're right but why the first code works then ? - TheKrm95
Short answers: Because there is nothing wrong with looping through Objects using for-in. Its just that the v-data-table is designed to loop through arrays. Just sanitize data so its in an array format. - Jeremy Walters

1 Answers

0
votes

type check failed for prop "items". Expected Array, got Object.

It is what it means. Datatable is fine with using data returned from promises as long as the type of response is an array. Your promise is returning an object.

The application works if instead of trying to diplay the dynamic data I try to display a statically defined object ("staticitems").

staticitems is not an object. It is an array of object. Arrays are displayed like this: [] and objects like {}

You need to make sure that the response coming back from an API is an array. I created a simple example from your API call to show you the right format of your response. As you can see info is now an array and the datatable works fine.