Is it possible to programmatically hide Vuetify data-table items? - javascript

I'm wondering if there is a way to hide a whole row/item in a vuetify data-table. I've read threads about hiding columns but not data-table items.

As per my understanding, You want to hide the specific rows from the <v-data-table>. If Yes, you can achieve that by using v-slot and manipulate the template.
Demo :
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
headers: [
{
text: 'Dessert',
value: 'name'
}
],
items: [
{
name: 'Frozen Yogurt',
show: true
},
{
name: 'Ice cream sandwich',
show: false
},
{
name: 'Eclair',
show: true
},
{
name: 'Cupcake',
show: false
}
]
}
},
})
<script src="https://unpkg.com/vue#2.x/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify#2.6.6/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify#2.6.6/dist/vuetify.min.css"/>
<link rel="stylesheet" href="https://unpkg.com/#mdi/font#6.x/css/materialdesignicons.min.css"/>
<div id="app">
<v-app id="inspire">
<v-data-table
:headers="headers"
:items="items"
class="elevation-1"
>
<template v-slot:item="props">
<template v-if="props.item.show">
<tr>{{ props.item.name }}</tr>
</template>
</template>
</v-data-table>
</v-app>
</div>

I think passing an empty array to your :items would fix your problem. or you can do this one :items="defaultVales || desserts".

In my opinion, the best way to handle this is to add a show property to your objects and use a computed property to hide and show items
Working example
Here it will hide column on click
new Vue({
el: '#app',
vuetify: new Vuetify(),
computed:{
showItems(){
return this.desserts.filter(x => x.show)
}
},
data() {
return {
headers: [
{ text: 'Name', value: 'name' },
{ text: 'Score', value: 'score' },
],
desserts: [{
name: "Frozen",
score: 66,
show: true,
},
{
name: "Tom",
score: 100,
show: true,
},
{
name: "Eclair",
score: 100,
show: true,
},
{
name: "Frozen",
score: 89,
show: true,
},
]
}
},
methods: {
hideColumn(col){
col.show = false
}
}
})
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/vuetify#2.3.4/dist/vuetify.min.css'>
<script src='https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js'></script>
<script src='https://cdn.jsdelivr.net/npm/vuetify#2.3.4/dist/vuetify.min.js'></script>
<div id="app">
<v-data-table
:items="showItems"
:headers="headers"
#click:row="hideColumn"
>
</v-data-table>
</div>

Related

Vue2 Reference method in data

In Vue2 this seems to be break:
<template>
<v-list v-model="itemSelected">
<v-list-item v-for="(item, i) in items" :key="i" #click="item.onClick"
>item.label</v-list-item>
</template>
<script>
export default {
name: 'myTestComponent'
data: () => ({
itemSelected,
items: [
{ label: 'Logout', onClick: this.onLogoutClick },
{ label: 'Settings', onClick: this.onSettingsClick },
{ label: 'Profile', onClick: this.onProfileClick },
]
}),
methods: {
onLogoutClick() {
console.log('LogoutClick')
},
onSettingsClick() {
console.log('SettingsClick')
},
onProfileClick() {
console.log('ProfileClick')
},
},
</script>
The error is that onLogoutClick is a null reference. This seems to indicate to me that the data property is created before the methods property.
Is there a way around this? Perhaps to pass the method names as a string and convert that reference to a method name at call time?
You can pass vue instance to data function, and call methods in onClick property :
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: (vi) => ({
itemSelected: null,
items: [
{ label: 'Logout', onClick: vi.onLogoutClick },
{ label: 'Settings', onClick: vi.onSettingsClick },
{ label: 'Profile', onClick: vi.onProfileClick },
]
}),
methods: {
onLogoutClick() {
console.log('LogoutClick')
},
onSettingsClick() {
console.log('SettingsClick')
},
onProfileClick() {
console.log('ProfileClick')
},
},
})
<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>
<v-list v-model="itemSelected">
<v-list-item v-for="(item, i) in items" :key="i" #click="item.onClick"
>{{item.label}}</v-list-item>
</v-list>
</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>

default sort not working in v-data-table Vuetify

I have users data fetched from the server which is sorted in desc order of age. When the users data is passed to the child component, it doesn't display data sorted in the desc order of the age in the v-data-table and when I refresh the page then it shows data sorted in the descending order. Please help me find where I am going wrong. I am using vuetify version 2.3.10
When the data is fetched from the server in the parent component it is as follows:
[{full_name: 'James Ross', city: 'Toronto', age: 45 },{full_name: 'Stacey Purkis', city: 'Calgary', age: 32 }, {full_name: 'Jazz Alzo', city: 'London', age: 24 }]
When the child component loads for the first time the users data is as follows:
[{full_name: 'Stacey Purkis', city: 'Calgary', age: 32 }, {full_name: 'Jazz Alzo', city: 'London', age: 24 }, {full_name: 'James Ross', city: 'Toronto', age: 45 }]
So basically it is not sorted and when I refresh the page then users data in the child component shows perfectly finish
[{full_name: 'James Ross', city: 'Toronto', age: 45 },{full_name: 'Stacey Purkis', city: 'Calgary', age: 32 }, {full_name: 'Jazz Alzo', city: 'London', age: 24 }]
parent component
<template>
<div>
<Users :users="users"></Users>
</div>
</template>
<script>
import Users from 'views/lawyers/_users_table.vue';
export default {
components: {
Users
},
data: () => ({
users: [],
}),
created: function() {
this.fetchUsers();
},
methods: {
fetchUsers() {
this.$axios.get('/users.json')
.then(response => {
this.users = response.data;
})
}
}
};
</script>
childcomponent
<template>
<div>
<v-data-table
:headers="headers"
:items="users"
:disable-pagination="true"
v-model="users"
hide-default-footer
class="elevation-1"
>
<template slot="item" slot-scope="props">
<tr>
<td class="full-name">{{ props.item.full_name }}</td>
<td class="summary">{{ props.item.address}}</td>
<td class="experience">{{ props.item.age }} years</td>
</tr>
</template>
</v-data-table>
</div>
</template>
<script>
export default {
props: ['users'],
data: () => ({
headers: [
{ text: 'Name', value: 'full_name', sortable: false },
{ text: 'Address', value: 'address', sortable: false },
{ text: 'Age',value: 'age' }
]
}),
};
</script>
The best way to keep it safe is to set sort-by in your data-table:
<v-data-table
:sort-by="['age']"
:headers="headers"
:items="users"
:disable-pagination="true"
v-model="users"
hide-default-footer
class="elevation-1"
>
[UPDATE]
To complete Václav Procházka's answer, you can also provide sort-desc to force it to be decrescent.
Also It's an anti-pattern since v2 to mutate props directly check docs here.
The ideal way is to make a clone of it or to use a computed property like below.
Using this.$emit('update:usersProp', val) will try to update your prop on parent component so you parent should look like this <Users :usersProp.sync="users"></Users> or if you use this.value and this.$emit(input, val), then you can use <Users v-model="users"></Users>. Docs here and here
new Vue({
el: '#app',
vuetify: new Vuetify(),
props: {
usersProp: {
default: () => {
return [
{full_name: 'Stacey Purkis', city: 'Calgary', age: 32 },
{full_name: 'Jazz Alzo', city: 'London', age: 24 },
{full_name: 'James Ross', city: 'Toronto', age: 45 }
]
}
}
},
data: () => ({
headers: [
{ text: 'Name', value: 'full_name', sortable: false },
{ text: 'Address', value: 'address', sortable: false },
{ text: 'Age',value: 'age' }
],
}),
computed: {
users: {
get () {
return this.usersProp
},
set (val) {
this.$emit('update:usersProp', val)
}
}
}
})
<!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#5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<div id="app">
<v-app>
<v-main>
<v-container>
<v-data-table
:headers="headers"
:items="users"
:sort-by="['age']"
:sort-desc="true"
:disable-pagination="true"
v-model="users"
hide-default-footer
class="elevation-1"
></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>
</body>
</html>

Vue, v-select component with true/false boolean

I have a v-select component from vuetify. I need to use boolean in this component with true, false and null options and I'm looking for solution how to do it in correct way
My code:
select.js
<template>
<v-row align="center">
<v-col cols="12">
<v-select
:items="items"
readonly
label="Read-only"
></v-select>
</v-col>
</v-row>
</template>
script.js
<script>
export default {
data: () => ({
items: ['Foo', 'Bar', 'Fizz', 'Buzz'],
}),
}
</script>
To use boolean values and null, your items should have the following structure :
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: () => ({
items: [
{
text: "true",
value: true
},
{
text: "false",
value: false
},
{
text: "null",
value: null
}
]
})
});

Set property of an object in an array VueJS?

So i am making a small list in which i have a list of car companies and an option for users to select their favorite one. I have an array of objects which returns the name and a certain property named starred. I have a method setStarred which sets the starred of selected to true. But what i am trying to achieve is to have the option to only select one at a time, so if i select BMW, the starred for other two should be toggled to false. Right now i can toggle all of them at the same time.
Please check this working codepen.
Check out the working example below:-
new Vue({
el: '#app',
data() {
return {
cars: [{
name: 'Toyota',
starred: false
},
{
name: 'BMW',
starred: false
},
{
name: 'Ford',
starred: false
}
]
}
},
methods: {
setStarred(item) {
item.starred = !item.starred
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet" />
<link rel="stylesheet" href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons'>
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout justify-center column>
<v-flex xs6 v-for="(car,index) in cars" :key="index">
<h2>{{car.name}}
<v-icon :color="car.starred ? 'primary': '' " #click="setStarred(car)">star_border
</v-icon>
</h2>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
Any help will be appreciated. Thank you.
You have to loop throw other array items and set their starred property to false. Or, you can store a data variable to indicate the index of the object which is currently stared.
new Vue({
el: '#app',
data() {
return {
cars: [{
name: 'Toyota',
starred: false
},
{
name: 'BMW',
starred: false
},
{
name: 'Ford',
starred: false
}
],
lastStarredIndex: null
}
},
methods: {
setStarred(index) {
if (this.lastStarredIndex === index) {
// toggle same item
this.cars[index].starred = !this.cars[index].starred;
if (this.cars[index].starred) this.lastStarredIndex = index;
else this.lastStarredIndex = null;
} else {
// disable last stared item
if (this.lastStarredIndex !== null) this.cars[this.lastStarredIndex].starred = false;
// set the new one
this.cars[index].starred = true;
this.lastStarredIndex = index;
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet" />
<link rel="stylesheet" href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons'>
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout justify-center column>
<v-flex xs6 v-for="(car,index) in cars" :key="index">
<h2>{{car.name}}
<v-icon :color="car.starred ? 'primary': '' " #click="setStarred(index)">star_border
</v-icon>
</h2>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
new Vue({
el: '#app',
data() {
return {
cars: [{
name: 'Toyota',
starred: false
},
{
name: 'BMW',
starred: false
},
{
name: 'Ford',
starred: false
}
]
}
},
methods: {
setStarred(item) {
// Set all to false
_.each(this.cars, function(value, key) {
value.starred = false;
});
item.starred = true
}
}
})
Solution
new Vue({
el: "#app",
data() {
return {
cars: [
{
name: "Toyota",
starred: false,
},
{
name: "BMW",
starred: false,
},
{
name: "Ford",
starred: false,
},
],
};
},
methods: {
setStarred(item) {
this.cars.forEach((car) => (car.starred = car.name === item.name));
},
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet" />
<link rel="stylesheet" href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons'>
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout justify-center column>
<v-flex xs6 v-for="(car,index) in cars" :key="index">
<h2>{{car.name}}
<v-icon :color="car.starred ? 'primary': '' " #click="setStarred(car)">star_border
</v-icon>
</h2>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
<v-icon :color="car.starred ? 'primary': '' " #click="setStarred(index)">star_border
</v-icon>
methods: {
setStarred(index) {
this.cars.map(i => {
i.starred = false
})
this.cars[index].starred = true
}
}

Vue Js: How to add serial number column in Vue Data Table Component

I am using <v-data-table> component to show data table in in my app. Is there any way to add the serial number column in this data-table. which starts from 1 to length of my articles array.
and it should start from 1 if any article with any id comes to first.
There is no built-in way to do this, but you can achieve it by adding a computed property and use .map() method to add a new property to each items like sno, which stands for serial number. You can rename it anything you want.
computed: {
itemsWithSno() {
return this.desserts.map((d, index) => ({ ...d, sno: index + 1 }))
}
},
Next, just add a new column in header array to map this new property like:
{
text: 'Serial #',
value: 'sno'
},
The value here needs to be exactly same as the new property name sno that you have added in the computed property.
Next, just update v-data-table items prop to use the computed property itemsWithSno instead of the original array like:
<v-data-table :headers="headers" :items="itemsWithSno">
</v-data-table>
That's it.
Working Demo:
new Vue({
el: '#app',
vuetify: new Vuetify(),
computed: {
itemsWithSno() {
return this.desserts.map((d, index) => ({ ...d, sno: index + 1 }))
}
},
data() {
return {
headers: [{
text: 'Serial #',
value: 'sno'
},
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name',
},
{
text: 'Calories',
value: 'calories'
},
{
text: 'Fat (g)',
value: 'fat'
}
],
desserts: [{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0
},
{
name: 'Eclair',
calories: 262,
fat: 16.0
},
{
name: 'Cupcake',
calories: 305,
fat: 3.7
},
{
name: 'Gingerbread',
calories: 356,
fat: 16.0
}
],
}
},
})
<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#2.x/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-data-table :headers="headers" :items="itemsWithSno" class="elevation-1">
</v-data-table>
</v-container>
</v-main>
</v-app>
</div>

Categories

Resources