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>
Related
I would like to create a table with a multiline header, like in this example.
I've found this post, however the answer does not work. Furthermore, I have looked at the Vuetify documentation and Github issues, but there seems to be no solution.
Would be great if someone could let me know whether something like this is possible and if so how.
It turns out you can simply implement your own categories line above the default headers if you just add <thead> in the slot template. Leaving out the <thead> puts it underneath.
<v-data-table ...>
<template v-slot:header="props" >
<thead>
<tr>
<th colspan="2">Category 1</th>
<th colspan="3">Category 2</th>
</tr>
</thead>
</template>
</v-data-table>
You can probably use slot="headerCell". Note that the version of Vuetify used here is 1.5.11
Here's a sample that might give you some pointers:
<v-data-table
v-bind:headers="headers"
v-bind:items="items"
v-bind:search="search"
v-bind:pagination.sync="pagination"
hide-actions
class="elevation-1"
>
<template slot="headerCell" scope="props">
<div slot="activator">
{{ props.header.text }}
</div>
<div>
<span>A</span>
<span>||</span>
<span>B</span>
</div>
</template>
<template slot="items" scope="props">
.....
</template>
</v-data-table>
Here's the codepen link : https://codepen.io/nizantz/pen/KYyLOp
Hope it helps your case.
(Note to moderator who deleted my earlier post: I accidentally posted the answer to a wrong question and I already deleted it.)
This is Core code
<v-data-table :headers="surgeryInformationHeaders" :items="surgeryInformationDesserts" hide-default-footer class="transparent elevation-0 my-4" hide-default-header disable-pagination disable-sort :items-per-page="5">
<template #header="{ }">
<thead class="v-data-table-header">
<tr>
<th v-for="(h,i) in surgeryInformationHeaders" :key="i" class="text-center parent-header td-border-style" :rowspan="h.children?1:2" :colspan="h.children?h.children.length:1">
{{ h.text }}
</th>
</tr>
<tr>
<th v-for="(h1,i1) in getSubHeader(surgeryInformationHeaders)" :key="i1" class="text-center child-header td-border-style">
{{ h1.text }}
</th>
</tr>
</thead>
</template>
<template #item="props">
<tr>
<td v-for="(c,ci) in getRows(props.item)" :key="ci">
{{ c }}
</td>
</tr>
</template>
</v-data-table>
Here's codeopen link https://codepen.io/sunhao1256/pen/MWeZyMe
Here's another sample that might help your case, based on your comment
Note that the data structure needs to be in the right format.(Child elements)
Vue-Template :
<div id="app">
<v-data-table
:headers="headersTop"
:items="tableitems"
hide-actions
>
<template slot="items" scope="props">
<td>
<v-data-table
:headers="[{text:'First Name', value:'fname', sortable:false},
{text:'Last Name', value:'lname', sortable:false}
]"
:items="props.item.name"
hide-actions
>
<template slot="items" scope="props">
<td>{{props.item.fname}}</td>
<td>{{props.item.lname}}</td>
</template>
</v-data-table>
</td>
<td>
<v-data-table
:headers="[{text:'Country', value:'country', sortable:false},
{text:'City', value:'city', sortable:false}
]"
:items="props.item.geo"
hide-actions
>
<template slot="items" scope="props">
<td>{{props.item.country}}</td>
<td>{{props.item.city}}</td>
</template>
</v-data-table>
</td>
</template>
</v-data-table>
</div>
Script:
new Vue({
el: '#app',
data () {
return {
pagination: {},
headersTop:[
{
text: 'Name',
value: 'name',
sortable: false,
},
{
text: 'Geo',
value: 'geo',
sortable: false,
}
],
tableitems:[{
name: [{
fname: 'Dakota',
lname: 'Rice'
},
{
fname: 'Minerva',
lname: 'Hooper'
}],
geo: [{
country: 'Niger',
city: 'Oud-Tunrhout',
},
{
country: 'CuraƧao',
city: 'Sinaai-Waas',
}]
}]
}
}
})
Heres's the codepen link : https://codepen.io/nizantz/pen/rbpNrY
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()
}
},
I have used Vuetify DataTables, in that DataTable I have multiple rows along with save button above the table.
Inside the Datatable,
textfield
select
When I write something in the text field and select the values from drop down select and click the save button, that row is moved from one page to another page.
Problem
Whatever selected from the drop-down and written in the textfield is get copied to the next row or you can say it is there for the next row which occupies the place for the moved row.
I want that it should not be there, i.e the textfield should be blank and no value will be selected for the next row.
Code:
<v-card v-if="resultedvalue">
<v-card-title>
<v-text-field
append-icon="search"
v-bind:label="$t('message.search')"
single-line
hide-details
v-model="search"
></v-text-field>
</v-card-title>
<v-data-table
v-bind:headers="headers"
v-bind:items="resultedvalue"
select-all
v-bind:search="search"
v-bind:pagination.sync="pagination"
class="elevation-1"
>
<template slot="headers" slot-scope="props">
<tr>
<th v-for="header in props.headers"
:key="header.text"
:class="['column sortable', pagination.descending ? 'desc' : 'asc',
header.value === pagination.sortBy ? 'active' : '']"
#click="changeSort(header.value)"
v-bind:align="header.align"
>
{{ $t(header.text) }}
<v-icon v-if="header.text.length > 0">arrow_upward</v-icon>
</th>
</tr>
</template>
<template slot="items" slot-scope="props">
<tr :active="props.selected" >
<td class="text-xs-left">{{ props.item.xyz}}</td>
<td class="text-xs-left">{{ props.item.abc}}</td>
<td class="text-xs-left">
<div>
{{props.item.ied}}<br>
{{props.item.dfshj}}
{{props.item.dfgnu}}
</div>
</td>
<td class="text-xs-left">
<div #click="show_dialog(props.item.dsfg,props.item.dfg)"
style= "cursor: pointer"
title="Click here to see details"
>
{{props.item.dfgfd}}
</div>
</td>
<td class="text-xs-left">
<v-text-field v-model="props.item.testvalue"></v-text-field>
</td>
<td class="text-xs-left">
<v-text-field
name="input-1"
label="Answer"
v-on:change="change_answer(props.item,$event)"
rows="1"
textarea
></v-text-field>
</td>
<td class="text-xs-left">
<v-select
v-bind:items="props.item.valuetobeselect"
v-on:change="changed(props.item,$event)"
label="Select"
single-line
bottom>
</v-select>
</td>
</tr>
</template>
</v-data-table>
Before Save
After Save
Change Event Methods:-
changed: function(element, item) {
element.somevalues = item;
this.selected_element= element;
},
change_answer:function(element,item){
var currentdate = new Date().toJSON();
element.somevalue = item;
element.somevalue1 = currentdate;
},
For the save button it is just calling the rest service and once the rest service is executed it called the initialized method which initializes the table .
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(...)
}
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]
}
}