manix
manix

Reputation: 14747

Vue - Array passed via v-bind is empty in computed properties

I am doing my first steps in vue starting with this little example. I am trying to achieve a sum of items according to data provided. (The complete example can be found in this jsffile)

The component:

Vue.component('items-table', {
    props: ['items', 'item', 'total'],
    template: `
        <div>
                <table>
                <thead>
                    <tr>
                        <th>Description</th>
                        <th>Price</th>
                    </tr>
                </thead>
                <tbody>
                    <tr
                        v-for="item of items"
                        v-bind:key="item.id"
                    >
                      <td>{{item.desc}}</td>
                      <td class="price">{{item.price}}</td>
                    </tr>
                </tbody>
            </table>
            
            
            <div>Total items: {{items.length}}</div>
            <div>Total price: {{total}}</div>
        </div>
    `
});

In the app below, the console prints an empty array, in consequence always returns 0:

new Vue({
  el: '#app',
    data:{
        items: []
    },
    computed: {
        total: function(){
            console.log(this.items);
            return this.items.reduce(function(total, item){

                return total + item.price;
            },0);
        }
    },
    mounted() {
        console.log('app mounted');
    }
});

Finally, I provide the initial data that will be used to display, manipulate and make some calculations:

<div id="app">
  <items-table v-bind:total="total" v-bind:items="[
            { id: 1, desc: 'Banana', price: 10 },
            { id: 2, desc: 'Pen', price: 5 },
            { id: 3, desc: 'Melon', price: 5 }
        ]"></items-table>

</div>

My problem is that the sum of the prices in {{total}} always is 0. Looks like the items array are never set when it is provided via v-bind:items (is it not reactive?). I appreciate the help in advance.

Edit: Backgrounds

All data that will be used for components comes from PHP plain files. CRUD operations are not available yet. Said that is very important that the data could be bind from tags directly.

Upvotes: 0

Views: 1472

Answers (1)

Gleyak
Gleyak

Reputation: 564

Your function calculating the total price uses the items object declared in the data tag of your view. Since its empty, the price is always 0. YOu should do something like:

    new Vue({
  el: '#app',
    data:{
        items: [
            { id: 1, desc: 'Banana', price: 10 },
            { id: 2, desc: 'Pen', price: 5 },
            { id: 3, desc: 'Melon', price: 5 }
        ]
    },
    computed: {
        total: function(){
            console.log(this.items);
            return this.items.reduce(function(total, item){

                return total + item.price;
            },0);
        }
    },
    mounted() {
        console.log('app mounted');
    }
})

And the vue should be more like this:

    <div id="app">
  <h2>List of items</h2>
  <items-table v-bind:total="total" v-bind={items}></items-table>

</div>

Hope it helps you with your problem

Edit: JSFiddle: https://jsfiddle.net/eywraw8t/210901/

Upvotes: 1

Related Questions