I have 2 computed arrays, homeTeam and awayTeam. The code below does work to generate 2 tables to display the homeTeam and awayTeam, how can I simplify the code to only create the table once and loop through the homeTeam and awayTeam. I tried wrapping it in a v-for with an array of ['homeTeam','awayTeam], but that did not work. The computed works, everything below works, I just want to simplify the template.
<v-flex xs12 md6>
<v-data-table :headers="headers" :items="homeTeam" hide-actions class="elevation-1 white">
<template slot="items" scope="props">
<td class="text-xs-right" v-model="gamesheet.number">{{ props.item.number }}</td>
<td v-model="gamesheet.name">{{ props.item.name }}</td>
</template>
</v-data-table>
</v-flex>
<v-flex xs12 md6>
<v-data-table :headers="headers" :items="awayTeam" hide-actions class="elevation-1 white">
<template slot="items" scope="props">
<td class="text-xs-right" v-model="gamesheet.number">{{ props.item.number }}</td>
<td v-model="gamesheet.name">{{ props.item.name }}</td>
</template>
</v-data-table>
</v-flex>
_
computed: {
homeTeam() {
return this.players.filter((player) => {
return player.team == this.gameinfo.home;
})
},
awayTeam() {
return this.players.filter((player) => {
return player.team == this.gameinfo.away;
})
},
spares() {
return this.players.filter((player) => {
return player.team != this.gameinfo.home && player.team != this.gameinfo.away;
})
},
},
here's my attempt with a v-for, I understand why this would not work.
<template v-for="roster in rosters">
<v-flex xs12 md6>
<v-data-table :headers="headers" :items="roster" hide-actions class="elevation-1 white">
<template slot="items" scope="props">
<td class="text-xs-right" v-model="gamesheet.number">{{ props.item.number }}</td>
<td v-model="gamesheet.name">{{ props.item.name }}</td>
<td class="text-xs-right" v-model="gamesheet.position">{{ props.item.position }}</td>
<td class="text-xs-right" v-model="gamesheet.goal">{{ props.item.goal }}</td>
<td class="text-xs-right" v-model="gamesheet.assist">{{ props.item.assist }}</td>
<td class="text-xs-right" v-model="gamesheet.team">{{ props.item.team }}</td>
</template>
</v-data-table>
</v-flex>
</template>
... and in the script...
data () {
return {
rosters: ['homeTeam', 'awayTeam'],
}
},
computed: {
homeTeam() {
return this.players.filter((player) => {
return player.team == this.gameinfo.home;
})
},
awayTeam() {
return this.players.filter((player) => {
return player.team == this.gameinfo.away;
})
},
I think you could use v-for in this way:
<template v-for="team in [homeTeam, awayTeam]">
<v-flex xs12 md6>
<v-data-table :headers="headers" :items="team" hide-actions class="elevation-1 white">
<template slot="items" scope="props">
<td class="text-xs-right" v-model="gamesheet.number">{{ props.item.number }}</td>
<td v-model="gamesheet.name">{{ props.item.name }}</td>
</template>
</v-data-table>
</v-flex>
</template>
There were a couple problems with your initial try. First computed values are not available to be used in the data function (they are initialized later). Second, you quoted the values, which means that rosters is just an array of two strings.
Another approach you could take would be to make rosters a computed value.
computed:{
rosters(){
return [this.homeTeam, this.awayTeam]
}
}
Related
rows per page is not working correctly, it locates at right side how can I fix it? firstly it didn't show then I added and in console it showed warning, than I added app-data = "true" then it was fixed, but dropdown didn't work correctly.
<template>
<div app-data="true">
<v-app id="app">
<v-content>
<v-card>
<v-card-title>
Nutrition
<v-spacer></v-spacer>
<v-text-field
v-model="search"
append-icon="search"
label="Search"
single-line
hide-details
></v-text-field>
</v-card-title>
<v-data-table
:headers="headers"
:items="desserts"
:search="search"
>
<template v-slot:items="props">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.calories }}</td>
<td class="text-xs-right">{{ props.item.fat }}</td>
<td class="text-xs-right">{{ props.item.carbs }}</td>
<td class="text-xs-right">{{ props.item.protein }}</td>
<td class="text-xs-right">{{ props.item.iron }}</td>
</template>
<template v-slot:no-results>
<v-alert :value="true" color="error" icon="warning">
Your search for "{{ search }}" found no results.
</v-alert>
</template>
</v-data-table>
</v-card>
</v-content>
</v-app>
</div>
</template>
I am facing a very weird situation with Vuetify forms. I have a Vuetify data table that follows the example used in the documentation as well as a dialog box that in fact includes a form. I am using prop to pass data from parent to child and I am following Vue and its best practice which consist of using prop as initial value for data variable. I then use to populate the form. I can edit the form and submit new values without any issue, but I created a cancel button that clears the form. when I do that, it also clears the parent fields that are in my data table. it is like the form reset is propagated from the child to its parent. so with the code hereunder, the {{props.item.order.dueDate}} is cleared when I clear the form of the child.v-bind is not supposed to behave like that.
I lost too many hours trying to find a reason but could not find anything
thanks
here is the code of the data table (parent)
<template>
<v-card>
<v-card-title class="display-3">
{{ tableTitle }}
<v-spacer></v-spacer>
<v-text-field
v-model="search"
append-icon="search"
label="Search"
single-line
hide-details
></v-text-field>
</v-card-title>
<v-data-table
:headers="headers"
:search="search"
:items="orderItems"
item-key="_id"
class="elevation-1"
:expand="expand"
>
<template v-slot:items="props">
<tr #click="props.expanded = !props.expanded">
<td class="px-2">{{ props.item.id }}</td>
<td class="text-xs px-2">{{ props.item.title }}</td>
<td class="text-xs px-2">{{ props.item.order.date | date }}</td>
<td class="text-xs px-2">{{ props.item.order.dueDate | date }}</td>
<td class="text-xs px-2">{{ props.item.count }}</td>
<td v-if="props.item.status" class="text-xs px-2">{{ props.item.status.type }}</td>
<td v-else class="text-xs px-2">New Order</td>
<td v-if="props.item.status" class="text-xs px-2"><span><v-icon color="green darken-2" v-if="props.item.status.signalSent">mail_outline</v-icon><v-icon #click.stop="sendSignal(props.item)" color="red darken-2" v-else>unsubscribe</v-icon> {{ props.item.status.datetime | date}}</span></td>
<td v-else class="text-xs px-2">-</td>
</tr>
</template>
<template v-slot:expand="props">
<v-card flat>
<list-orders-details v-bind:order="props.item"></list-orders-details>
</v-card>
<v-btn
#click.stop="showDialog()"
color="red darken-2"
fixed
dark
small
bottom
right
fab
>
<v-icon>edit</v-icon>
</v-btn>
<v-dialog v-model="editOrder" persistent>
<edit-order-item ref="clearEdit" v-bind:itemChild="props.item"></edit-order-item>
<v-btn class="cancel" dark color="red darken-2" #click="cancelEdit()">cancel</v-btn>
</v-dialog>
</template>
<v-alert slot="no-results" :value="true" color="error" icon="warning">
Your search for "{{ search }}" found no results.
</v-alert>
</v-data-table>
</v-card>
</template>
in the script of the parent:
cancelEdit() {
this.editOrder=false
this.$refs.clearEdit.clear()
}
and an extract of the child :
<template>
<v-form
#submit.prevent
ref="form"
class="white"
>
<v-container>
<h4>Status</h4>
<v-divider class="red darken-2"></v-divider>
<v-layout row wrap align-center justify-start>
<v-flex xs12 sm4 md3>
<v-select
:items="status"
v-model="orderItem.itemStatus.type"
outline
label="Status"
></v-select>
...
export default {
name: 'EditOrderItem',
components: {
},
props: ['itemChild'],
data() {
return {
dialog: false,
order: {
apikey: this.itemChild.order.apikey,
orderId: this.itemChild.order.id,
...
},
},
methods: {
submit () {
const formContent = {
order_id: this.itemChild.order._id,
item_id: this.itemChild._id,
order: this.order,
item: this.orderItem,
}
console.log(formContent)
},
clear () {
this.$refs.form.reset()
}
},
This is my code for UI part:
<div>
<v-data-table :headers="headers" :items="items">
<template slot="items" slot-scope="props">
<tr #click="showDialog(props.item)">
<td>{{ props.item.company_name }}</td>
</tr>
</template>
</v-data-table>
<v-dialog v-model="dialog">
{{form}}
</v-dialog>
</div>
this is my script code:
data(){
return{
dialog: false,
form: {}
}
},
methods: {
showDialog(data){
this.dialog = true
this.form = data
}
}
Now my problem is, v-dialog won't open even if the variable 'dialog' is equal to true. How can I show the dialog box?
Try
<tr>
<td #click="showDialog(props.item)">{{ props.item.company_name }}</td>
</tr>
so the click will execute on every element 'company_name' of the table.
Also you can add a new column with a button to call the function
<td>
<v-btn icon class="mx-0" #click="showDialog(props.item)">
<v-icon color="black">edit</v-icon>
</v-btn>
</td>
I have the following code:
<v-app>
<v-content>
<v-container fluid full-height>
<v-layout row wrap>
<v-flex xs12>
<v-data-table
hide-actions
:headers='headers'
:items='items'
class='elevation-1'
></v-data-table>
</v-flex>
</v-layout>
</v-container>
</v-content>
</v-app>
in the script section:
data: {
headers: [
{text: 'Name', value: 'name'},
{text: 'Age', value: 'age'}
],
items: [
{
name: 'John',
age: 30
}
]
}
https://jsfiddle.net/eywraw8t/507618/
I do not understand why I'm just getting the header of the table and not the data.
Can someone help me?
You have to define your table cells within the "items" slot of the v-data-table component. Headers render automatically, you can specify a "header" slot from customer headers. Checkout out this codepen from the Vuetify Docs on datatables. Notice the template within the v-data-table element that is defining the "items" slot.
<template>
<v-data-table
:headers="headers"
:items="desserts"
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.calories }}</td>
<td class="text-xs-right">{{ props.item.fat }}</td>
<td class="text-xs-right">{{ props.item.carbs }}</td>
<td class="text-xs-right">{{ props.item.protein }}</td>
<td class="text-xs-right">{{ props.item.iron }}</td>
</template>
</v-data-table>
</template>
Just define a slot with your table cells. In your code you have already added items props. You need to populate items inside a slot with data-table cells.
Here is your code with new changes.
<v-app>
<v-content>
<v-container fluid full-height>
<v-layout row wrap>
<v-flex xs12>
<v-data-table
hide-actions
:headers='headers'
:items='items'
class='elevation-1'
>
<template slot="items" slot-scope="props">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.age }}</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-container>
</v-content>
</v-app>
If you need more information read the docs
Hope this helps.
I cant filter my current visible result in my datatable without triggering a new api call. Each time I click on one of the columns the datatable makes a new API call to the very same page, so its not even appending any parameters to the api call like order desc etc.. So how can I filter my result without making a new api call
My code:
<v-card>
<v-card-title>
My data
<v-spacer></v-spacer>
<v-flex xs2>
<v-text-field
append-icon="search"
label="Search data"
single-line
hide-details
v-model="search"
></v-text-field>
</v-flex>
</v-card-title>
<v-data-table
:headers="headers"
:items="items"
:total-items="pagination.totalItems"
:pagination.sync="pagination"
:search="search"
item-key="combo_id"
:rows-per-page-items="[50, 50]"
hide-actions
>
<template slot="items" slot-scope="props">
<tr #click="getCombo(props.item.combo_id); props.expanded = !props.expanded">
<td class="text-xs-left">{{ props.item.data }}</td>
<td class="text-xs-left">{{ props.item.data2 }}</td>
<td class="text-xs-left">{{ props.item.data3 }}</td>
<td class="text-xs-left">{{ props.item.data4 }}</td>
<td class="text-xs-left">{{ props.item.data5 }}</td>
<td class="text-xs-left">{{ props.item.data6 }}</td>
<td class="text-xs-left">{{ props.item.data7 }}</td>
</tr>
</template>
<template slot="expand" slot-scope="props">
<v-card flat>
<v-card-text>
<v-btn color="primary" dark #click.stop="commentDialog = true">Show comments</v-btn> Tags: <strong>{{ comboItemTags }}</strong>
<v-btn color="warning" class="right" #click.stop="editDialog = true">Edit system</v-btn>
</v-card-text>
</v-card>
</template>
</v-data-table>
<div class="text-xs-center pt-2">
<v-pagination v-model="pagination.page" :length="pages" :total-visible="10"></v-pagination>
</div>
</v-card>
data () {
return {
search: '',
items: [],
pagination: {
page: 1,
rowsPerPage: 50,
totalItems: 0
},
...
...
},
watch: {
pagination: {
handler() {
this.getAllSystemsNewPage(this.pagination.page); //Fetch new data and push into items
},
deep: true
}
},
If you're fetching data from a server and watching the pagination object, it's assumed that all processing (pagination, sorting, searching) happens server-side.
See this example. Everything that happens inside the promise in getDataFromApi is a simulation of what happens on the server. You will need to pass along the relevant data from the pagination object as parameters to your server API call and return the correct items.
edit:
How you pass along the pagination data to your backend is outside of vuetify's scope and depends on what the backend looks like. But a simple example is something like this:
getDataFromApi () {
const { sortBy, descending, page, rowsPerPage } = this.pagination
const query = `page=${page}&sort_by=${sortBy}&sort_order=${descending ? 'desc' : 'asc'}&rows_per_page=${rowsPerPage}`
axios.get(`/api/endpoint?${query}`).then(...)
}