How to dynamically change the header of a v-data-table? - vue.js

I'm trying to make a v-data-table that is populated with json data (Vue + Vuetify + Vue-Resource). I can show the data without problems, but I need to change the first colum of the header to let visible what data the user is viewing actually.
At this moment I'm using a static header without the label that I want:
headers: [
{
text: "",
align: "left",
sortable: false,
value: "name",
id: "primeiraColunaColuna"
},
{ text: "total QTD", value: "total QTD" },
{ text: "total", value: "Total" },
{ text: "Date", value: "Date" },
{ text: "Time", value: "Time" }
],
I want to make the text field change to A, B, C, D, etc.
There's anyway to make this happen?

You can return headers from a method, that takes the text as a parameter, for example you could use the current index in a loop:
<v-layout>
<v-flex v-for="i in 3" xs4>
<v-data-table
:headers="getHeaders(i)"
:items="desserts"
class="elevation-1"
>
<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>
</template>
</v-data-table>
</v-flex>
</v-layout>
methods:{
getHeaders(headingText){
return [
{
text: 'Dynamic heading no. ' +headingText,
align: 'left',
sortable: false,
value: 'name'
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' }
];
}
}
live example: https://codepen.io/sf-steve/pen/pYgOze

Related

Show data from api to a table in vue js

How do i display data from the database. I have fetched data as an object when displaying it works well but when i convert the data to array it does not display the content of the table.
Am also trying to implement the routing such that when one clicks the button on the Actions column it redirect to another page that has a specific user details.
Am getting the data from the API and in the network fetch xhr am able to see the data.
This is the vue template where i want to display the data received by the API I guess am going wrong somewhere
<v-data-table hide-actions flat :headers="headers" :="doctors">
<template v-slot:items="props">
<td>{{ props.index + 1 }}</td>
<td>{{ props.item.full_name }}</td>
<td>{{ props.item.email }}</td>
<td>{{ props.item.username }}</td>
<td>{{ props.item.username }}</td>
<td>
<v-btn outline small color="indigo" #click="view(props.item)">
<i class="fa fa-eye"></i> make payment
</v-btn>
</td>
</template>
<template v-slot:no-results>
<h6 class="grey--text">No data available</h6>
</template>
</v-data-table>
</div>
</template>
<script>
import {mapActions, mapGetters} from "vuex";
export default {
data() {
return {
page: 1,
dateFormat: "DD MMM, YYYY",
selected: null,
dialog: false,
loading: false,
saveLoader: false,
headers: [
{text: "#", value: ""},
{text: "name", value: "name"},
{text: "email", value: "email"},
{text: "role", value: "role"},
{text: "updated_at", value: "updated_at"},
{text: "Action", value: "action"},
],
};
},
computed: {
...mapGetters({
doctors: "getListDoctors",
}),
},
methods: {
...mapActions({
fetchDoctors: 'setListDoctors'
}),
view(id) {
this.$router.push({ path: `/finance/pay-doctors/${item.id, '_blank'}` });
}
},
mounted() {
this.fetchDoctors();
},
}
</script>
Here is sample of data received from the API
{
"data": [
{
"id": 1,
"name": "TEST JOHN",
"full_name": "Mrs. JOHN",
"mobile": "0700000001",
"email": "TEST#TEST.com",
"active": 0,
"created_at": "Sep 10, 2019 07:01:43 am",
"roles": "testpharm",
"username": "USER1"
},
]
}
This should work fine regarding the doc
<template>
<v-data-table hide-actions flat :headers="headers" :items="doctors" :items-per-page="5">
<template v-slot:body="{ items }">
<tbody>
<tr v-for="item in items" :key="item.id">
<td>{{ item.name }}</td>
<td>{{ item.full_name }}</td>
<td>{{ item.mobile }}</td>
<td>{{ item.email }}</td>
<td>{{ item.username }}</td>
</tr>
</tbody>
</template>
<template v-slot:no-results>
<h6 class="grey--text">No data available</h6>
</template>
</v-data-table>
</template>
<script>
import { mapActions, mapGetters } from "vuex";
export default {
data() {
return {
headers: [
{ text: "#", value: "" },
{ text: "name", value: "name" },
{ text: "email", value: "email" },
{ text: "role", value: "role" },
{ text: "updated_at", value: "updated_at" },
{ text: "Action", value: "action" },
],
};
},
computed: {
...mapGetters({
doctors: "getListDoctors",
}),
},
async mounted() {
await this.fetchDoctors();
},
}
</script>
Use your Vue devtools to be sure to pass data.data to the final doctors Vuex getter (regarding your JSON example).
Vue devtools will help you see what state you currently have + the usage of the network tab can also help quite a lot.

VUETIFY DataTable - How to use v-if on table header to hide certain column from users

I am trying to hide the action for non-admin users. I am using a data-table to do it. Here is my code:
<v-data-table
dense
:headers="stampedDocumentsHeaders"
:items="filterCutOffAllDocs"
:search="searchAllDoc"
loading-text="Loading... Please wait">
<template v-slot:body="{items}">
<tbody>
<tr v-if="filterCutOffAllDocs.length == 0">
<td colspan="8" style="text-align:center;color:#808080;font-size:18px;padding:10px">NO DATA TO SHOW</td>
</tr>
<tr v-else v-for="(item, i) in items" :key="i">
<td style="text-align:center">{{item.document_control_code}}</td>
<td style="text-align:center">{{item.document_title}}</td>
<td style="text-align:center">{{item.request_type}}</td>
<td style="text-align:center">{{item.nature_of_request}}</td>
<td style="text-align:center">{{item.status}}</td>
<td style="text-align:center">{{item.s_date}}</td>
<td style="text-align:center">{{item.StamperName}}</td>
</tr>
</tbody>
</template>
</v-data-table>
Here is the header in my data:
headersData: [
{ text: "Code", value: "document_control_code" },
{ text: "Request Type", value: "request_type"} ,
{ text: "Title", value: "document_title" },
{ text: "department", value: "department" },
{ text: "Request Date", value: "request_date" },
{ text: "Due Date", value: "due_date" },
{ text: "Action", value: "action" },
]
It should work like this:
data() {
return {
headersData: [
{ text: "Code", value: "document_control_code" },
{ text: "Request Type", value: "request_type"} ,
{ text: "Title", value: "document_title" },
{ text: "department", value: "department" },
{ text: "Request Date", value: "request_date" },
{ text: "Due Date", value: "due_date" },
]
}
},
and in mounted()
mounted() {
if(admin) {
this.headersData.push({ text: "Action", value: "action" });
}
}

Vuejs, vuetify Data table how to make multi search value in 1 search box?

how can make the search filtering by 2 or more columns ,
example searching for: first name and last name in the same query not only one of them.
Tried Adding custom filter but not working.
...
<v-text-field v-model="search" append-icon="search" label="Search..." single-line hide-details></v-text-field>
<v-data-table :headers="headers" :items="theMainList" :search="search" >
<template v-slot:items="props">
<td>{{ props.item.id }}</td>
<td>{{ props.item.first_name}}</td>
<td>{{ props.item.last_name}}</td>
<td>{{ props.item.phone}}</td>
</template>
<template v-slot:no-results>
<v-alert :value="true" color="error" icon="warning">No Search Result "{{search}}"</v-alert>
</template>
</v-data-table>
<script>
export default {
data() {
return {
search: '',
headers: [{
text: 'id',
align: 'left',
value: 'id'
},
{
text: 'First Name',
align: 'left',
value: 'first_name'
},
{
text: 'Last Name',
align: 'left',
value: 'last_name'
},
{
text: 'Phone Number',
align: 'left',
value: 'phone'
},
],
},
</script>
...
thanks,
The custom filters in Vuetify are currently broken: https://github.com/vuetifyjs/vuetify/issues/12136
Current's best solution is to filter the items (theMainList) yourself with a computed function.

How to combine an Expandable Table with an Expansion Panel in Vuetify?

I'd like to combine two separate Vuetify functionalities into one:
https://vuetifyjs.com/en/components/data-tables --> Expandable Rows Table (but ideally with more than one data row upon expansion)
https://vuetifyjs.com/en/components/expansion-panels --> External Control Expansion Panel
Ultimately, the goal is to have a table that looks like this (Grouping Table with expand/collapse all one): https://codepen.io/lzhoucs/pen/aadaJx
The issue with this table is that despite fitting the code into my project, certain functionalities don't work -- such as clicking to open and close a table. I believe this is due to this being a different version of Vue than what I'm using, which is the most up to date, as I spotted some old styles.
I've tried a bunch of things, but my most successful attempt is creating a table within a table. Here is the code for that:
<template>
<v-container>
<v-data-table
:headers="headers"
:items="projects"
:expanded="expanded"
item-key="name"
show-expand
class="elevation-1"
#click:row="clicked"
>
<template v-slot:expanded-item="{ headers }">
<td :colspan="headers.length">
<v-data-table
:headers="peopleHeaders"
:items="people"
item-key='name'
hide-default-footer
class='elevation-1'>
<template slot="item" slot-scope="props">
<tr>
<td>{{props.item.name}}</td>
<td>{{props.item.major}}</td>
<td>{{props.item.preference}}</td>
<td>
<v-btn color='success'>Accept</v-btn>
<v-btn color='error'>Reject</v-btn>
</td>
</tr>
</template>
</v-data-table>
</td>
</template>
</v-data-table>
</v-container>
</template>
<script>
export default {
data() {
return {
expanded: [],
headers: [
{
text: 'Name',
align: 'left',
sortable: true,
value: 'name',
},
{ text: 'Status', value: 'Status' },
],
projects: [
{
name: '#this is the project they applied to',
Status: 'Status: Pending',
},
],
peopleHeaders: [
{
text: 'Name',
align: 'left',
sortable: true,
value: 'name',
},
{
text: 'Major',
align: 'left',
sortable: true,
value: 'major',
},
{
text: 'Preference',
align: 'left',
sortable: true,
value: 'preference',
},
],
people: [
{
name: 'BORB',
major: 'SWE',
preference: 'idk',
},
],
};
},
methods: {
clicked(value) {
this.expanded.push(value);
},
},
};
</script>
Any advice for how to combine the two features to achieve the table desired would be greatly appreciated.

Vue + Vuetify data table first column image

I am using Vue + Vuetify and I am trying to add image in the first column.
Table Template Code
<v-data-table
:headers="headers"
:items="desserts"
:search="search"
light
>
<template slot="items" slot-scope="props">
<td><img :src="props.item.name" style="width: 50px; height: 50px"></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-alert slot="no-results" :value="true" dir="rtl" color="error" icon="warning">
{{ PRODUCTS_TABLE_TEXT.NO_RESULT }} "{{ search }}"
</v-alert>
</v-data-table>
Table Script Code
data () {
return {
//TEXT
PRODUCTS_TABLE_TEXT: products_table_text,
//TABLE DATA
search: '',
headers: [
{
text: products_table_text.columns.IMAGE,
align: 'center',
sortable: false,
value: 'image'
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' }
],
desserts: [
{
value: false,
name: '1.jpg',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: '1%'
},
]
}
}
What I have tried to do
I have tried to add the HTML image code in the name variable like this:
name: '<img src="./../../assets/products-images/1.jpg" style="width: 50px; height: 50px">'
But it just printed the HTML as a text and did not render it.
I am also stacked for som minute but this is the easy way to use an image in vuetify data table
Table Template Code
<template>
<v-layout row wrap>
<v-flex xs12>
<v-data-table :headers="headers" :items="carts" class="elevation-0">
<template v-slot:item.image="{ item }">
<div class="p-2">
<v-img :src="item.image" :alt="item.name" height="100px"></v-img>
</div>
</template>
</v-data-table>
</v-flex>
</v-layout>
<template/>
Table Script Code
<script>
import { mapGetters } from "vuex";
export default {
data() {
return {
user: null,
isAvalibel: false,
headers: [
{ text: "Image", value: "image", sortable: false },
{ text: "Product Name", value: "name", sortable: false },
]
};
computed: {
...mapGetters(["carts"])
},
During template compilation, the compiler can transform certain attributes, such as src URLs, into require calls, so that the target asset can be handled by webpack. For example, <img src="./foo.png"> will attempt to locate the file ./foo.png on your file system and include it as a dependency of your bundle.
so, for dynamic attribute src,
<td>
<img :src="require('./assets/products-images/' +props.item.name)">
</td>
Actually there are many ways you can use to insert image inside your Vue app/template:
1) (This is what you need for your code) Using require function actually this is going to be handled by the webpack and map the image to it's resource.
<img :src="require('./assets/products-images/' + props.item.name)">
please follow the below github discussion for more explanation:
https://github.com/vuejs-templates/webpack/issues/126
2) Another way read the image as base64 from the server and handle that inside your Vue app:
<img v-bind:src="'data:image/jpeg;base64,'+imageBytes" />
if you want to use your server images with axios and display them in the rows, this works too.
<template v-slot:item.image="{ item }">
<img v-bind:src="`/${item.image}`" style="width: 50px; height:50px">
</v-img>
</template>