v-data-table change color selected row - vue.js

I would like to change the background color of the selected row in a v-data-table.
<v-data-table dense :headers="headers"
:items="records"
#click:row="handleClick"> <!-- handleClick is a function that logs item for the moment... -->
<template v-slot:[`item.index`]="{item}">
<v-row justify="center">
<v-col>
<div>{{item.index}}</div>
</v-col>
</v-row>
</template>
<template v-slot:[`item.status`]="{ item }">
<v-row justify="center">
<v-col v-if="item.status===1">
<v-icon color="green">
mdi-check-circle
</v-icon>
</v-col>
<v-col v-else>
<v-icon color="orange">
mdi-progress-check
</v-icon>
</v-col>
</v-row>
</template>
</v-data-table>
I couldn't find a way to distinguish the selected row from the others and thus update the style for the selected one.
Basically i'd like to reproduce the behavior implemented for the v-list component.

Selected rows have the v-data-table__selected class applied on their TR tag - so you can just create some CSS override to target them. The default style in Vuetify is
.theme--light.v-data-table tbody tr.v-data-table__selected
{
background: #f5f5f5;
}

You can use item-key="index" and single-select to select row and set class tr.v-data-table__selected:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
headers: [{text: 'index', value: 'index'}, {text: 'status', value: 'status'}],
records: [{index: 1, status: 1}, {index: 2, status: 0}, {index: 3, status: 1}],
selected: null
}
},
methods: {
handleClick(item, row) {
row.select(true);
this.selected = item
}
}
})
tr.v-data-table__selected {
background: lime !important;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-main>
<v-container>
<div>{{ selected }}</div>
<v-data-table dense :headers="headers"
:items="records" item-key="index" single-select
#click:row="handleClick">
<template v-slot:[`item.index`]="{item}">
<v-row justify="center">
<v-col>
<div>{{item.index}}</div>
</v-col>
</v-row>
</template>
<template v-slot:[`item.status`]="{ item }">
<v-row justify="center">
<v-col v-if="item.status===1">
<v-icon color="green">
mdi-check-circle
</v-icon>
</v-col>
<v-col v-else>
<v-icon color="orange">
mdi-progress-check
</v-icon>
</v-col>
</v-row>
</template>
</v-data-table>
</v-container>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>

Related

How to order object in v-for to stay on top Vue 2

I have an expansion panel and a v-for on it. I want to keep the panel with the same id as the logged-in user on top, and the others render last. My code is like it now:
<v-expansion-panels>
<v-expansion-panel v-for="(sign, index) in demandSignatures" :key="index">
<v-expansion-panel-header
#click="dataEdit(sign)"
:hide-actions="userID !== sign.userEid"
:disabled="userID !== sign.userEid"
>
<v-row>
<v-col cols="1"></v-col>
<v-col cols="4">
{{ sign.userFullName }}
</v-col>
<v-col>
<span
v-if="sign.signatureStatus === 'Accepted'"
class="text-success"
>امضا شده</span
>
<span
v-else-if="sign.signatureStatus === 'Rejected'"
class="text-danger"
>رد شده</span
>
<span
v-else-if="sign.signatureStatus === 'pending'"
class="text-warning"
>در انتظار تایید</span
>
</v-col>
</v-row>
</v-expansion-panel-header>
<v-expansion-panel-content v-if="userID === sign.userEid">
<v-divider />
<v-card-text class="mt-3">
<v-textarea
label="توضیحات"
v-model="description"
outlined
dense
></v-textarea>
</v-card-text>
<v-card-actions class="mx-4 justify-end d-flex">
<v-btn
class="me-2"
icon
small
#click="signForm(sign.eid, 'Accepted', acceptText)"
>
<v-icon small color="teal">mdi-draw-pen</v-icon>
</v-btn>
<v-btn
class="ms-2"
icon
small
#click="signForm(sign.eid, 'Rejected', rejText)"
>
<v-icon small color="red">mdi-close</v-icon>
</v-btn>
</v-card-actions>
<v-divider />
</v-expansion-panel-content>
<v-expansion-panel-content v-else></v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
I want to keep the panel with this condition v-if="userID === sign.user-id on top
Can anyone help with it?
Modify your demandSignatures data by plucking the item whose id is equal to userID and put it in the first position. You can do this job on the mounted hook.
Here is the working demo-
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
</head>
<body>
<div id="app">
<v-app>
<v-expansion-panels>
<v-expansion-panel v-for="(sign, index) in demandSignatures" :key="sign.userEid">
<v-expansion-panel-header
#click="dataEdit(sign)"
:hide-actions="userID !== sign.userEid"
:disabled="userID !== sign.userEid"
>
<v-row>
<v-col cols="1"></v-col>
<v-col cols="4">
{{ sign.userFullName }}
</v-col>
<v-col>
<span
v-if="sign.signatureStatus === 'Accepted'"
class="text-success"
>امضا شده</span
>
<span
v-else-if="sign.signatureStatus === 'Rejected'"
class="text-danger"
>رد شده</span
>
<span
v-else-if="sign.signatureStatus === 'pending'"
class="text-warning"
>در انتظار تایید</span
>
</v-col>
</v-row>
</v-expansion-panel-header>
<v-expansion-panel-content v-if="userID === sign.userEid">
<v-divider />
<v-card-text class="mt-3">
<v-textarea
label="توضیحات"
v-model="description"
outlined
dense
></v-textarea>
</v-card-text>
<v-card-actions class="mx-4 justify-end d-flex">
<v-btn
class="me-2"
icon
small
#click="signForm(sign.eid, 'Accepted', acceptText)"
>
<v-icon small color="teal">mdi-draw-pen</v-icon>
</v-btn>
<v-btn
class="ms-2"
icon
small
#click="signForm(sign.eid, 'Rejected', rejText)"
>
<v-icon small color="red">mdi-close</v-icon>
</v-btn>
</v-card-actions>
<v-divider />
</v-expansion-panel-content>
<v-expansion-panel-content v-else></v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
userID: 3,
description: null,
demandSignatures: [{
userEid: 1,
userFullName: "I am not equal to userID",
signatureStatus: "Accepted"
},
{
userEid: 2,
userFullName: "I am not equal to userID",
signatureStatus: "pending"
},
{
userEid: 3,
userFullName: "I am equal to userID",
signatureStatus: "Rejected"
},
{
userEid: 4,
userFullName: "I am not equal to userID",
signatureStatus: "Rejected"
},
],
};
},
mounted() {
this.reOrder();
},
methods: {
reOrder() {
// Find the index of item who match with userID
let index = this.demandSignatures.findIndex(
(item) => item.userEid == this.userID,
);
// If item found
if (index != -1) {
// save it in some local variable
let item = this.demandSignatures[index];
// remove it from its current position
this.demandSignatures.splice(index, 1);
// and put it at the first position
this.demandSignatures.unshift(item);
}
},
dataEdit() {},
signForm() {},
},
})
</script>
</body>
</html>

How to not loop a particular item in a card in vuetify

can Any one help me... I want to show card-title only in card-1. I don't want to show the card-title in card-2 card-3 and card-4.
<v-app>
<v-row v-for="(item, index) in list" :key="index">
<v-col cols="12">
<v-card>
<v-card-title>
<v-avatar size="60" color='primary'>{{item.avatarText}}</v-avatar>
</v-card-title>
<v-card-text>{{item.name}}</v-card-text>
</v-card>
</v-col>
</v-row>
</v-app>
</template>
<script>
export default{
data(){
return{
list:[{name:'apple1',avatarText:'Abc',},
{name:'apple2'},
{name:'apple3'},
{name:'apple4'}]
}
}
Using v-if, you can check for the index:
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: () => ({
list:[ {name:'apple1', avatarText:'Abc'}, {name:'apple2'}, {name:'apple3'}, {name:'apple4'} ]
})
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script><link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<v-app id="app">
<v-row v-for="(item, index) in list" :key="index">
<v-col cols="12">
<v-card>
<v-card-title v-if="index === 0">
<v-avatar size="60" color='primary'>{{item.avatarText}}</v-avatar>
</v-card-title>
<v-card-text>{{item.name}}</v-card-text>
</v-card>
</v-col>
</v-row>
</v-app>

vuetify :v-date-picker error on changing calendar type

to see error
1.switch type to month
2.select a months range
3.change type to date
then you will see this error :
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
modal : false ,
currentLocale : 'en',
selectOptions : [
{ key: 'date', value: 'Date' },
{ key: 'month', value: 'Month' }
],
calType : 'date',
range : true,
date : []
}
},
methods: {
selectType($event) {
this.calType = $event;
},
},
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app id="inspire">
<v-row justify="center">
<v-col cols="12">
<v-select
v-model="calType"
label="select date type"
item-text="value"
item-value="key"
:items="selectOptions"
dense
single-line
v-on:change="selectType($event)"
>
</v-select>
</v-col>
<v-col cols="12">
<v-dialog
ref="dialog"
v-model="modal"
:return-value.sync="date"
persistent
width="290px"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
v-model="date"
label="Picker in dialog"
prepend-icon="mdi-calendar"
readonly
v-bind="attrs"
v-on="on"
></v-text-field>
</template>
<v-date-picker
v-model="date"
:locale="currentLocale"
:range="range"
:type="calType"
:first-day-of-week="1"
scrollable
>
<v-spacer></v-spacer>
<v-btn text color="primary" #click="modal = false">
Cancel
</v-btn>
<v-btn text color="primary" #click="$refs.dialog.save(date)">
OK
</v-btn>
</v-date-picker>
</v-dialog>
</v-col>
</v-row>
</v-app>
</div>
so, how can i fix this ?
also this is another photo

Background image with opacity in a card

I have a login form in a card, i put a background image on it using the img prop, but I want to add opacity to it, I guess I will have to use some vanilla CSS on this but I don't really know how to approach it, when I inspect the element it adds the image as an inline style instead of using some <img> tag. Is there a way I could add opacity using the v-img component or do I have to do everything with vanilla CSS?
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
show: false,
}
},
})
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-container>
<v-row no-gutters>
<v-col cols="12" sm="12">
<v-card class="rounded-0 mx-auto" flat max-width="480" img="https://i.picsum.photos/id/845/200/200.jpg?hmac=KMGSD70gM0xozvpzPM3kHIwwA2TRlVQ6d2dLW_b1vDQ">
<!-- Login form -->
<v-form>
<v-container>
<v-row no-gutters>
<v-col cols="12" sm="12">
<v-text-field label="Username/Email" color="brown lighten-1" placeholder="Username/Email" outlined></v-text-field>
</v-col>
<v-col cols="12" sm="12">
<v-text-field placeholder="Password" outlined color="brown lighten-1" :append-icon="show ? 'mdi-eye' : 'mdi-eye-off'" :type="show ? 'text' : 'password'" label="Password" #click:append="show = !show"></v-text-field>
</v-col>
<v-btn block class="rounded-0 white--text" color="#887783">Login</v-btn>
</v-row>
</v-container>
</v-form>
</v-card>
</v-col>
</v-row>
</v-container>
</v-app>
</div>

When I delete one in the v-expansion-panel it opens the next one for me. How to undo it

expansion-panel and when I delete one from the array it automatically opens the next one for me.
how can I undo it?
Thanks
<v-expansion-panel
v-for="(Test, index) in Test"
:key="index">
<v-expansion-panel-header>
<template v-slot:actions>
<v-icon color="green">fa fa-check</v-icon>
</template>
</v-expansion-panel-header>
<v-expansion-panel-content>
<v-col cols="4">
<v-btn
text
color="primary"
#click="
delete(Test)
"
>delete</v-btn
>
</v-col>
</v-expansion-panel-content>
</v-expansion-panel>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
active: null,
test: [1, 2, 3, 4, 5]
}),
methods: {
del(index) {
this.test.splice(index, 1)
this.active = null
}
}
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-main>
<v-container>
<v-expansion-panels v-model="active">
<v-expansion-panel v-for="(t, index) in test" :key="index">
<v-expansion-panel-header>
item
</v-expansion-panel-header>
<v-expansion-panel-content>
<v-col cols="4">
<v-btn text color="red" #click="del(index)">delete{{t}}</v-btn>
</v-col>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</v-container>
</v-main>
</v-app>
</div>
Using value prop:
Controls the opened/closed state of content in the expansion-panel. Corresponds to a zero-based index of the currently opened content.
Set this.active = null after each deletion to keep the panel closed.