Vue + Vuetify data table first column image - vue.js

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>

Related

How to open a new page with the props id of a specific user on blank page and set route

I have a code have fetched from the laravel backend and passed it to vue frontend. the data is a table with records. I have already implemented it.
I have a payment tab which i want it to redirect to a specific page using the id to display data of the individual.
I have tried the router-push how do i implement it
this is my implementation code
<template>
<v-data-table hide-actions flat :headers="headers" :items="doctors" :pagination.sync="pagination"
:rows-per-page-items="pagination.rowsPerPageItems"
:total-items="pagination.totalItems">
<template v-slot:items="props">
<td>{{ props.index + 1 }}</td>
<td>{{ props.item.full_name }}</td>
<td>{{ props.item.email }}</td>
<td>{{ 'Doctor' }}</td>
<td><button class="disabled btn btn-success">amount</button></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 class="text-center">
<v-pagination
v-model="page"
:length="4"
circle
>
</v-pagination>
</div>
</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,
pagination: {
descending: true,
page: 1,
rowsPerPage: 10,
sortBy: 'fat',
totalItems: 0,
rowsPerPageItems: [1, 2, 4, 8, 16]
},
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() {
console.log(this.doctors)
// window.open(`/finance/pay-doctors/${item.id}`, "_blank");
},
},
async mounted() {
await this.fetchDoctors();
},
}
</script>
Try this.
let routeData = this.$router.resolve({name: 'routeName', query: {data: "someData"}});
window.open(routeData.href, '_blank');

How to add icon to the Header in vuetify DataTable

I'm trying to add (+) icon to the one of the header columns in v-datatable.
The code below does not add any icon. Actually, creating template slot for header does not have any effect on datatable.
What I try,
<template>
<v-data-table
item-key="name"
:items="complainantInfos"
:headers="headers"
sort-by="Id"
class="elevation-1">
<template v-slot:top>
<v-toolbar flat color="white">
<v-toolbar-title>Inspection</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
</template>
<template slot="headers" slot-scope="props">
<tr>
<th
v-for="header in props.headers"
:key="header.text">
<v-icon small >plus-circle-outline</v-icon>
{{ header.text }}
</th>
</tr>
</template>
</v-data-table>
</template>
<script>
import { mapGetters } from "vuex";
export default {
data(){
return{
complainantInfos:[
{
...
}
],
headers: [
{ text: 'NameSurname', value: 'name', align: 'left' ,width: "25%" },
{ text: 'ID', value: 'PersonelIdNumber' },
{ text: 'Phone-1', value: 'Cellular1' },
{ text: 'Phone-2', value: 'Cellular2' },
{ text: 'Work Phone', value: 'WorkPhone' },
{ text: 'InterPhone', value: 'Interphone' },
{ text: 'Email', value: 'Email' },
//{ text: '+', value: 'action', sortable: false, align: 'right'}
],
I have edited the code according to the comments. The problem solved.
...
</v-card>
</v-form>
</v-dialog>
</v-toolbar>
</template>
<template v-slot:header.Actions="{ header }">
<v-icon small>plus-circle-outline</v-icon>{{ header.text }}
</template>
...
Since you only wish to add the icon to one specific column, I would suggest header.columnName.
Your slot would look like this:
<template v-slot:header.name="{ header }">
<v-icon small>plus-circle-outline</v-icon>{{ header.text }}
</template>
If the column name is "Cellular1", the code will be <template v-slot:header.Cellular1="{ header }">.
Please make sure you have the icon set included. Otherwise, no HTML will be rendered for v-icon. You can test it with default mdi icons, for example mdi-minus.

vuetity) How to put an image in a v-data-table

<v-data-table
:headers="headers"
:items="items"
:search="search"
:loading="loading"
loading-text="Loading... Please wait"
hide-default-footer
class="elevation-1"
>
<template slot="items">
<td>
<img :src="items.imgsrc" style="width: 50px; height: 50px" />
</td>
</template>
</v-data-table>
Between v-data-table tags
I think I should put in an image with slots, etc., but I don't know at all. I'm asking because I can't find the exact code no matter how hard I look.
The height in the 'v-img' tag seems to work, but the image doesn't come out.
<script>
export default {
data () {
return {
search: '',
headers: [
{
text: 'img',
align: 'start,
filterable: false,
value: 'imgsrc',
type: 'Image',
},
{
text: 'MyName',
align: 'start,
filterable: false,
value: 'name',
},
],
items: [
{
name: 'test1',
imgsrc: '#/assets/img/avatar.png',
},
{
name: 'test2',
imgsrc: '#/assets/img/avatar2.png',
},
],
}
},
}
</script>
Help me
The slot needs to be used like below
<v-data-table
:headers="headers"
:items="items"
:search="search"
:loading="loading"
loading-text="Loading... Please wait"
hide-default-footer
class="elevation-1"
>
<template v-slot:item.imgsrc="{ item }">
<td>
<img :src="require(item.imgsrc)" style="width: 50px; height: 50px">
</td>
</template>
</v-data-table>

Pass data to a component called inside v-data-table

I have a v-data-table and I added an expandable div to each of them that I want to use as a component. I'm not sure how to pass the data from the selected v-data-table to the component. I'm using single file components.
ScanGrid component(parent):
<template>
<v-container>
<v-card>
<v-card-text>
<v-layout row align-center>
<v-data-table
:headers="headers"
:items="items"
:hide-actions="true"
item-key="id"
>
<template slot="items" slot-scope="props">
<tr #click="props.expanded = !props.expanded">
<td>{{ props.item.name }}</td>
<td class="text-xs-right pr-5">{{ props.item.scanned }}</td>
<td class="text-xs-right pr-5">{{ props.item.incoming }}</td>
<td class="text-xs-right pr-5">{{ props.item.outgoing }}</td>
<td class="text-xs-right pr-5">{{ props.item.unknown }}</td>
</tr>
</template>
<div :value="items">
<ScanGridChild></ScanGridChild>
</div>
</v-data-table>
</v-layout>
</v-card-text>
</v-card>
</v-container>
</template>
<script>
import ScanGridChild from "./ScanGridChild";
export default {
name: "ScanGrid",
props: {},
components: {
ScanGridChild
},
data: () => ({
selected: [],
items: [
{
id: 1,
name: "Location 1",
scanned: 159,
incoming: 6,
outgoing: 24,
unknown: 4,
test: "Test 1"
},
{
id: 2,
name: "Location 2",
scanned: 45,
incoming: 6,
outgoing: 24,
unknown: 4,
test: "Test 2"
}
],
totalResults: 0,
loading: true,
pagination: {},
headers: [
{
text: "Localisation",
sortable: true,
value: "name"
},
{
text: "Paquets scannés",
sortable: true,
value: "scanned"
},
{
text: "Paquets entrants",
sortable: true,
value: "incoming"
},
{
text: "Paquets sortants",
sortable: true,
value: "outgoing"
},
{
text: "Paquets inconnus",
sortable: true,
value: "unknown"
}
]
}),
mounted() {},
methods: {},
watch: {}
};
</script>
<style lang="scss" scoped></style>
ScanGridChild component(What I want to use for the expanded div in the v-data-table item):
<template v-slot:expand="props">
<v-card flat>
<v-card-text>{{ props.item.test }}</v-card-text>
</v-card>
</template>
<script>
export default {
name: "ScanGridChild",
props: {
value: {
Type: String,
Required: true
}
},
async mounted() {
await this.render();
},
computed: {},
watch: {
props: function(newVal, oldVal) {
console.log("Prop changed: ", newVal, " | was: ", oldVal);
this.render();
}
}
};
</script>
<style></style>
I'm on Vuetify 1.5.19.
I think my problem is with the slot-scope in ScanGrid but I'm not sure.
Your code is almost correct, You need to add some additional fix to parent and child component
Parent component
<template>
<v-container>
<v-card>
<v-card-text>
<v-layout row align-center>
<v-data-table
:headers="headers"
:items="items"
:hide-actions="true"
item-key="id"
>
<template slot="items" slot-scope="props">
<tr #click="props.expanded = !props.expanded">
<td>{{ props.item.name }}</td>
<td class="text-xs-right pr-5">{{ props.item.scanned }}</td>
<td class="text-xs-right pr-5">{{ props.item.incoming }}</td>
<td class="text-xs-right pr-5">{{ props.item.outgoing }}</td>
<td class="text-xs-right pr-5">{{ props.item.unknown }}</td>
</tr>
</template>
<template slot="expand" slot-scope="props">
<ScanGridChild v-bind:testName="props.item.test"></ScanGridChild>
</template>
</v-data-table>
</v-layout>
</v-card-text>
</v-card>
</v-container>
</template>
In Child Component
<template>
<v-card flat>
<v-card-text>{{ testName }}</v-card-text>
</v-card>
</template>
<script>
export default {
name: "ScanGridChildComponent",
props: {
testName: {
Type: String,
Required: true
}
}
};
</script>

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

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