There is probably a really simple fix to this problem but I cannot seem to get it to work correctly. I am using a Vuetify data table to loop through and show all my properties but it does not seem to work correctly when I use a computed property. I am trying to combine a few props (street, city, state, zip) into a computed address prop. So when I use each prop individually it works fine like this:
<td class="text-xs-center">{{ props.item.street }}</td>
<td class="text-xs-center">{{ props.item.city }}</td>
<td class="text-xs-center">{{ props.item.state }}</td>
<td class="text-xs-center">{{ props.item.zip }}</td>
However, if in the script section of my Vue template, I create a computed property "fullAddress" like:
computed: {
fullAddress () {
return this.street & '\n' & this.city & ', ' & this.state & ' ' & this.zip
}
}
then use that in the template above like:
<td class="text-xs-center">{{ props.item.fullAddress() }}</td>
it does not work at all. I have also tried numerous other ways to write it out but nothing has worked. I am new to Vue and how it uses computed properties so I am sure that I am just not understanding how it works properly.
EDIT: I am using a Vuetify data table to loop through my data. I am using their documentation to display the table. Like I said, I am new to Vue so I am trying to figure all this out. I believe the :items="items" is a v-bind for all the props (similar to a v-for loop?). Here is a more complete example of what Vuetify has for a very simple data table:
<template>
<v-data-table
:headers="headers"
:items="items"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.street }}</td>
<td class="text-xs-right">{{ props.item.city }}</td>
<td class="text-xs-right">{{ props.item.state }}</td>
<td class="text-xs-right">{{ props.item.zip }}</td>
</template>
</v-data-table>
</template>
<script>
export default {
data () {
return {
headers: [
{
text: 'Name',
sortable: false,
value: 'name'
},
{ text: 'Street', value: 'street' },
{ text: 'City', value: 'city' },
{ text: 'State', value: 'state' },
{ text: 'Zip Code', value: 'zip' }
],
items: [
{
name: 'Braums',
street: '159 W Elm St',
city: 'St. Louis',
state: 'MO',
zip: 83607
},
{
name: 'McDonalds',
street: '237 N Cup Way',
city: 'Dallas',
state: 'TX',
zip: 47621
}
]
}
}
}
</script>
Thank you for expanding your question.
What you can't do: you can't have an array of computeds, because computeds aren't associated with data items, they are associated with the component. The way you proposed writing it, the computed would have to have a different this
for each item
. But its this
is the component.
You can create a computed based on items
that returns each value in items
augmented with the fullAddress
value you compute for that item. Note that you should be careful not to modify your original item
; I use Object.assign
to create a new copy.
Then you pass the computed array to your v-table instead of passing items
.
I just plugged the new variable in in place of street to show that it works.
Vue.use(Vuetify);
new Vue({
el: '#app',
data() {
return {
headers: [{
text: 'Name',
sortable: false,
value: 'name'
},
{
text: 'Street',
value: 'street'
},
{
text: 'City',
value: 'city'
},
{
text: 'State',
value: 'state'
},
{
text: 'Zip Code',
value: 'zip'
}
],
items: [{
name: 'Braums',
street: '159 W Elm St',
city: 'St. Louis',
state: 'MO',
zip: 83607
},
{
name: 'McDonalds',
street: '237 N Cup Way',
city: 'Dallas',
state: 'TX',
zip: 47621
}
]
}
},
computed: {
itemsWithFullAddress() {
// This creates a new empty object, copies the item into it,
// then calculates `fullAddress` and copies that entry into it
return this.items.map((obj) => Object.assign({}, obj, {
fullAddress: `${obj.street}\n${obj.city}, ${obj.state} ${obj.zip}`
}));
}
}
});
<link href="//unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet" />
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<script src="//unpkg.com/vuetify/dist/vuetify.min.js"></script>
<div id="app">
<v-data-table :headers="headers" :items="itemsWithFullAddress" hide-actions class="elevation-1">
<template slot="items" slot-scope="props">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.fullAddress }}</td>
<td class="text-xs-right">{{ props.item.city }}</td>
<td class="text-xs-right">{{ props.item.state }}</td>
<td class="text-xs-right">{{ props.item.zip }}</td>
</template>
</v-data-table>
</div>