Show only hovered <v-icon> in Vuetify data table - javascript

i have a Vuetify data table with headers and data field respectively and in the props.item.name i have added a v-icon but i only wanna show that icon only when i hover over that respective field. By default it should not show up.
I have added the Code below with the script and HTML.
And here is a a pen
Any help will be appreciated on how to achieve that.
new Vue({
el: '#app',
data() {
return {
headers: [{
text: 'Dessert (100g serving)',
align: 'left',
sortable: false,
value: 'name'
},
{
text: 'Calories',
value: 'calories'
},
{
text: 'Fat (g)',
value: 'fat'
},
{
text: 'Carbs (g)',
value: 'carbs'
},
{
text: 'Protein (g)',
value: 'protein'
},
{
text: 'Iron (%)',
value: 'iron'
}
],
desserts: [{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: '1%'
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: '1%'
},
{
name: 'Eclair',
calories: 262,
fat: 16.0,
carbs: 23,
protein: 6.0,
iron: '7%'
},
{
name: 'Cupcake',
calories: 305,
fat: 3.7,
carbs: 67,
protein: 4.3,
iron: '8%'
},
]
}
}
})
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.18/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.18/dist/vuetify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<v-app id="inspire">
<v-data-table :headers="headers" :items="desserts" class="elevation-1">
<template v-slot:items="props">
<td>{{ props.item.name }}
<v-icon right>cake</v-icon></td>
<td>{{ props.item.calories }}</td>
<td>{{ props.item.fat }}</td>
<td>{{ props.item.carbs }}</td>
<td>{{ props.item.protein }}</td>
<td>{{ props.item.iron }}</td>
</template>
</v-data-table>
</v-app>
</div>

Add a data property called for example c_index (current index) and when you hover over the row you assign the hovered index to c_index and reset it to -1 when the mouse the leaves it:
<tr #mouseover="c_index=props.index" #mouseleave="c_index=-1">
and show that icon conditionally like :
<v-icon right v-show="props.index==c_index">cake</v-icon>
Full Demo

Using a v-hover component, inside the v-slot:item.column_name of a data table, you can pass a prop through its v-slot, and used it like this:
<template v-slot:item.action="{ item }">
<v-hover v-slot:default="{ hover }">
<v-badge
:value="hover"
color="deep-purple accent-4"
content="First Button"
left
transition="slide-x-transition"
>
<v-icon>mdi-fountain-pen-tip</v-icon>
</v-badge>
</v-hover>
</template>
Also you can use the v-hover with the css, but you have to fix the position.
Full Demo

Your best option is CSS
_ On v-icon hover :
.v-data-table .v-icon{visibility:hidden}
.v-data-table .v-icon:hover{visibility:visible}
_ On td container hover
.v-data-table td .v-icon{visibility:hidden}
.v-data-table td:hover .v-icon:hover{visibility:visible}
This will affect all v-icons in your template, to be more precise add a class to the v-icons you want to hide.
...
<v-icon class="hidden" ... />
...
.hidden{visibility:hidden}
.hidden:hover{visibility:visible}
or
...
<td class="hidden" >
<v-icon ...>
...
</td>
...
.hidden .v-icon{visibility:hidden}
.hidden:hover .v-icon{visibility:visible}

Related

how fixed column width of vuetify data table

I have a vuetify data table, I've set width for every column and I want to fixed column's width of my table but it has grown up because of their content and it doesn't matter what is the width of them.
how can fixed column's width?
<template>
<v-data-table
v-if="physicianAccountsLocalData"
:headers="headers"
:items="physicianAccountsLocalData"
hide-default-footer
class="data-table"
:items-per-page="-1"
>
<template #[`item.isActive`]="props">
<BaseSwitch
v-model="props.item.isActive"
class="switch-siam-table"
#change="changeModel($event, props)"
/>
</template>
<template #[`item.location`]="props">
<span
class="location"
:class="{'text-disable-state': !props.item.isActive}"
>
{{ props.item.location }}
</span>
</template>
<template #[`item.name`]="props">
<span
class="name"
:class="{'text-disable-state': !props.item.isActive}"
>
{{ props.item.name }}
</span>
</template>
</v-data-table>
</template>
<script>
data() {
return {
headers: [
{ text: 'فعال', value: 'isActive', sortable: false, width: '110px', align: 'right' },
{ text: 'نوع', value: 'location', sortable: false, width: '13%', align: 'start' },
{ text: 'نام', value: 'name', sortable: false, width: '200px' }
],
}
}
</script>

want to show image in data table row

i want to show a image in vuetify data table row. i tried this with below code.
<v-data-table :headers="headers" :items="desserts" :search="search" class="elevation-1">
<template slot="items" slot-scope="props">
<td>
<img :src="'/assets/img/' + 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>
<template v-slot:item.action="{ item }">
<v-icon small class="mr-2" #click="editItem(item)">edit</v-icon>
<v-icon small #click="deleteItem(item)">delete</v-icon>
</template>
</v-data-table>
but this code not works properly. only shows data with v-data-table loop and template slot not working. my script like this.
search: "",
headers: [
{
text: "Images",
align: "left",
sortable: false,
value: "name"
},
{ text: "Calories", value: "calories" },
{ text: "Fat (g)", value: "fat" },
{ text: "Carbs (g)", value: "carbs" },
{ text: "Protein (g)", value: "protein" },
{ text: "Iron (%)", value: "iron" },
{ text: "Actions", value: "action", sortable: false }
],
desserts: [
{
value: false,
name: "notfound.png",
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: "1%"
}],
how can i show my image. this method only shows image text name only.
Presuming you use the last version of vuetify, the slots are working a little bit different, and you can define a slot only for the column you want to customize. (order is defined by the headers)
<div id="app">
<v-data-table :headers="headers" :items="desserts" class="elevation-1">
<template v-slot:item.name="{ item }">
<img :src="'/assets/img/' + item.name" style="width: 50px; height: 50px" />
</template>
<template v-slot:item.action="{ item }">
<v-icon small class="mr-2" #click="editItem(item)">edit</v-icon>
<v-icon small #click="deleteItem(item)">delete</v-icon>
</template>
</v-data-table>
</div>

Data is recognized but not rendered Vuetify

I have an assignment that uses Vuetify and I want to render a table of "customer" data. My code worked fine with Vuetify 1.5, but now I am supposed to update to the newest version, which is 2.0.
The problem I'm running into is that my data is recognized by the program, but none of it actually shows up in the table. The exact number of rows are rendered to match my number of records, and Vue DevTools shows that my data is there, but The rendered html is just empty elements. I attached screenshots below to illustrate my point a little better:
The project can be found at: https://github.com/apalmesano2/assign3_frontend.git
Here is a snippet of what my Vue template for the list of customers:
CustomerList.vue
<template>
<main>
<br />
<v-container fluid grid-list-md>
<v-layout column align-left>
<blockquote>
Welcome {{validUserName}}!
<footer>
<small>
<em>—Eagle Financial Services, your Midwest Financial Services Partner.</em>
</small>
</footer>
</blockquote>
</v-layout>
<v-layout column align-center>
<v-flex xs6 sm8 md7>
<v-alert
v-if="showMsg === 'new'"
dismissible
:value="true"
type="success"
>New customer has been added.</v-alert>
<v-alert
v-if="showMsg === 'update'"
dismissible
:value="true"
type="success"
>Customer information has been updated.</v-alert>
<v-alert
v-if="showMsg === 'deleted'"
dismissible
:value="true"
type="success"
>Selected Customer has been deleted.</v-alert>
</v-flex>
</v-layout>
<br />
<v-container fluid grid-list-md fill-height>
<v-layout column>
<v-flex md6>
<v-data-table
:headers="headers"
:items="customers"
hide-default-footer
class="elevation-1"
fixed
style="max-height: 300px; overflow-y: auto"
>
<template slot="items" slot-scope="props">
<td>{{ props.item.pk }}</td>
<td>{{ props.item.cust_number }}</td>
<td>{{ props.item.name }}</td>
<td nowrap="true">{{ props.item.address }}</td>
<td nowrap="true">{{ props.item.city }}</td>
<td nowrap="true">{{ props.item.state }}</td>
<td nowrap="true">{{ props.item.zipcode }}</td>
<td nowrap="true">{{ props.item.email }}</td>
<td nowrap="true">{{ props.item.cell_phone }}</td>
<td nowrap="true">
<v-icon #click="updateCustomer(props.item)">edit</v-icon>
</td>
<td nowrap="true">
<v-icon #click="deleteCustomer(props.item)">delete</v-icon>
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-container>
<v-btn class="blue white--text" #click="addNewCustomer">Add Customer</v-btn>
</v-container>
</main>
</template>
And the script, although I don't think there is an issue here because the data is being fetched just fine according to the Vue DevTools:
<script>
import router from "../router";
import { APIService } from "../http/APIService";
const apiService = new APIService();
export default {
name: "CustomerList",
data: () => ({
customers: [],
validUserName: "Guest",
customerSize: 0,
showMsg: "",
headers: [
{ text: "Record Number", sortable: false, align: "left" },
{ text: "Customer Number", align: "left", sortable: false },
{ text: "Name", sortable: false, align: "left" },
{ text: "Address", sortable: false, align: "left" },
{ text: "City", sortable: false, align: "left" },
{ text: "State", sortable: false, align: "left" },
{ text: "ZipCode", sortable: false, align: "left" },
{ text: "Email", sortable: false, align: "left" },
{ text: "Phone", sortable: false, align: "left" },
{ text: "Update", sortable: false, align: "left" },
{ text: "Delete", sortable: false, align: "left" }
]
}),
mounted() {
this.getCustomers();
this.showMessages();
},
methods: {
showMessages() {
console.log(this.$route.params.msg);
if (this.$route.params.msg) {
this.showMsg = this.$route.params.msg;
}
},
getCustomers() {
apiService
.getCustomerList()
.then(response => {
this.customers = response.data.data;
this.customerSize = this.customers.length;
if (
localStorage.getItem("isAuthenticates") &&
JSON.parse(localStorage.getItem("isAuthenticates")) === true
) {
this.validUserName = JSON.parse(localStorage.getItem("log_user"));
}
})
.catch(error => {
if (error.response.status === 401) {
localStorage.removeItem("isAuthenticates");
localStorage.removeItem("log_user");
localStorage.removeItem("token");
router.push("/auth");
}
});
},
addNewCustomer() {
if (
localStorage.getItem("isAuthenticates") &&
JSON.parse(localStorage.getItem("isAuthenticates")) === true
) {
router.push("/customer-create");
} else {
router.push("/auth");
}
},
updateCustomer(customer) {
router.push("/customer-create/" + customer.pk);
},
deleteCustomer(customer) {
apiService
.deleteCustomer(customer.pk)
.then(response => {
if (response.status === 204) {
alert("Customer deleted");
this.showMsg = "deleted";
this.$router.go();
}
})
.catch(error => {
if (error.response.status === 401) {
localStorage.removeItem("isAuthenticates");
localStorage.removeItem("log_user");
localStorage.removeItem("token");
router.push("/auth");
}
});
}
}
};
</script>
I have a hunch I'm doing something wrong with my v-data-table and the template where I'm passing the props in but I can't figure out what's going wrong or how to fix it because even just hardcoded text in the tags won't render in the table.
To access the page where the screenshots are after cloning the project, you would need to log in with the following credentials:
Username: instructor
Password: instructor1a
Thanks to anyone who can help!
I figured out the new syntax after moving to vuetify v2:
<v-data-table
:headers="headers"
:items="stocks"
hide-default-footer
class="elevation-1"
fixed
style="max-height: 300px; overflow-y: auto"
>
<template v-slot:item="props">
<tr>
<td>{{ props.item.customer }}</td>
<td nowrap="true">{{ props.item.symbol }}</td>
<td nowrap="true">{{ props.item.name }}</td>
<td nowrap="true">{{ props.item.shares }}</td>
<td nowrap="true">{{ props.item.purchase_price }}</td>
<td nowrap="true">{{ props.item.purchase_date }}</td>
<td nowrap="true">
<v-icon #click="updateStock(props.item)">edit</v-icon>
</td>
<td nowrap="true">
<v-icon #click="deleteStock(props.item)">delete</v-icon>
</td>
</tr>
</template>
</v-data-table>

How to display a datatable through an accordion

I encountered some troubles creating an accordion table. I created an Accordion component and a Table component. While independant from each other it works perfectly fine but I can't get any table appear into accordion.
//js part of accordion component
import Table from "../Table/index.vue"
export default {
name: 'accordion',
components: { Table },
mounted () {
},
data(){
return {
items: [
{ id: "mc", title: "Medical Checkup", text: this.components.Table },
{ id: "ac", title: "Application connected", text:
this.components.Table },
{ id: "p", title: "Programs", text: this.components.Table },
{ id: "pl", title: "Pain list", text: this.components.Table }
]
}
}
}
//html part of accordion component
<div>
<div ref="list" class="list">
<transition-group class="flip-list" name="flip-list" ref="tg1"
tag="div">
<div v-for="(item,index) in items" :key="item.id" class="item">
<slot name="item" :class="{active:item.isOpen}" :item="item"
:index="index">
<v-expansion-panel id="exp1">
<v-expansion-panel-content>
<div slot="header" class="drop-target handle2">
<span>{{item.title}}</span>
</div>
<v-card>
<v-card-text>
<div slot="item">{{Table}}</div>
</v-card-text>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
</slot>
</div>
</transition-group>
</div>
</div>
So, the point is : how can I make it so that a datatable appears into accordion ? Like when you click aon one of the titles and it appears instead of some text ?
Thanks a lot
Resolved!
In case of (if people encounter the same problem as I had), here is the code (html / js).
//html goes here
<div id="app">
<v-app id="inspire">
<v-data-table :headers="mainHeaders"
:items="mainItems"
item-key="title"
hide-actions
expand
class="elevation-1">
<template slot="items" scope="props">
<tr #click="props.expanded = !props.expanded">
<td class="text-xs">{{ props.item.title }}</td>
</tr>
</template>
<template slot="expand" scope="props">
<v-data-table :headers="subHeaders"
:items="subItems"
item-key="pain"
hide-actions
class="elevation-10">
<template slot="items" scope="props">
<td class="text-xs">{{ props.item.pain }}</td>
<td class="text-xs">{{ props.item.type }}</td>
</template>
</v-data-table>
</template>
</v-data-table> </v-app>
</div>
//js goes here
export default {
name: 'accordion-table',
mounted () {
},
data () {
return {
mainHeaders: [
{ text: 'Medical informations', value: 'title' }
],
mainItems: [
{ title: 'Medical Checkup' },
{ title: 'Application connected' },
{ title: 'Programs' },
{ title: 'Pain List' }
],
subHeaders: [
{ text: 'Pain', value: 'pain' },
{ text: 'Type', value: 'type' }
],
subItems: [
{ pain: 'Knee', type: '1' },
{ pain: 'Ankle', type: '2' },
{ pain: 'Back', type: '3' },
{ pain: 'Neck', type: '4' }
]
}
}
}
(I used random values)
Hope it helps some of you

Bootstrap Vue Dynamic table templating

I am working with Bootstrap Vue JS table component to create a datatable:
https://bootstrap-vue.js.org/docs/components/table
I am new to VueJS and am uncertain on how to approach this problem which makes searching for a solution even more complicated.
I use an API endpoint to return JSON data:
{
"options":{
"filter":false
},
"fields":[
{
"key":"id",
"label":"Id",
"editLink":false,
"display":true,
"sortable":true,
"class":"shrink"
},
{
"key":"name",
"label":"Name",
"editLink":true,
"display":true,
"sortable":true
}
],
"data":[ ]
}
Here is my table template:
<b-table striped hover bordered foot-clone class="table-sm"
:items="users" :fields="displayedFields" :per-page="perPage" :current-page="currentPage" :filter="filter"
#filtered="onFiltered"
>
<template v-for="(field, index) in fields">
<template slot="{{field.key}}" slot-scope="row" v-if="field.editLink">
<router-link :to="'/user/' + row.item.id" v-bind:key="index"></router-link>
</template>
</template>
<template slot="status" slot-scope="row">
<toggle-button :width="36" :height="18" v-model="row.status" :labels="false" :colors="{checked: '#00FF00', unchecked: '#FF0000', disabled: '#CCCCCC'}"/>
</template>
</b-table>
The first template tag is an attempt from a wild guess. I want to be able to conditionally select a table for a column from the fields config. You can see in my attempt that I want to put a RouterLink when the field's config editLink is true.
How can I get this done?
If you're using version 2.0.0 or newer of bootstrap-vue you need to change the slot names as
they've changed, and the old vue slot has also been deprecated in favor for v-slot.
I changed the accepted answers fiddle to work with the new naming and v-slot
new Vue({
el: "#app",
data: {
fields: [{
key: "id",
label: "Id",
colType: "span"
}, {
key: "name",
label: "Name",
colType: "button"
}, {
key: "uhh",
label: "uhh..",
colType: "idk"
}],
items: [{
id: 0,
name: "Test 0"
}, {
id: 1,
name: "Test 1"
}, {
id: 2,
name: "Test 2"
}]
}
});
<link href="https://unpkg.com/bootstrap#4.3.1/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue#2.0.0/dist/bootstrap-vue.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.0.0/dist/bootstrap-vue.js"></script>
<div id="app">
<b-table :items="items" :fields="fields">
<template v-for="(field, index) in fields" v-slot:[`cell(${field.key})`]="data">
<div v-if="field.colType === 'button'">
<h5>{{data.item.name}}</h5>
<b-button>Am Button</b-button>
</div>
<div v-else-if="field.colType === 'span'">
<h5>{{data.item.name}}</h5>
<span>Am Span</span>
</div>
<div v-else>
<h5>{{data.item.name}}</h5>
Am Confused
</div>
</template>
</b-table>
</div>
Here's a jsfiddle showing dynamic columns with a b-table:
https://jsfiddle.net/nardnob/wvk6fxgt/
new Vue({
el: "#app",
data: {
fields: [{
key: "id",
label: "Id",
colType: "span"
}, {
key: "name",
label: "Name",
colType: "button"
}, {
key: "uhh",
label: "uhh..",
colType: "idk"
}],
items: [{
id: 0,
name: "Test 0"
}, {
id: 1,
name: "Test 1"
}, {
id: 2,
name: "Test 2"
}]
}
});
<div id="app">
<b-table :items="items" :fields="fields">
<template v-for="(field, index) in fields" :slot="field.key" slot-scope="data">
<div v-if="field.colType === 'button'">
<h5>{{data.item.name}}</h5>
<b-button>Am Button</b-button>
</div>
<div v-else-if="field.colType === 'span'">
<h5>{{data.item.name}}</h5>
<span>Am Span</span>
</div>
<div v-else>
<h5>{{data.item.name}}</h5>
Am Confused
</div>
</template>
</b-table>
</div>

Categories