Toggle Hide/Show element VueJS? - javascript

I am using a Vuetify data table with header and item slots. Now i have a button which by default should be hidden but i only want to show it when a row is selected or when all of them are selected. I assumed i should be able to use the selected data property but that seems to stay empty if i select one row. So not sure how i can hide/show the button.
This is a working pen.
This is the code:-
new Vue({
el: "#app",
data: () => ({
pagination: {
sortBy: "name"
},
selected: [],
headers: [{
text: "Dessert (100g serving)",
align: "left",
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
}
]
}),
methods: {
toggleAll() {
if (this.selected.length) this.selected = [];
else this.selected = this.desserts.slice();
},
changeSort(column) {
if (this.pagination.sortBy === column) {
this.pagination.descending = !this.pagination.descending;
} else {
this.pagination.sortBy = column;
this.pagination.descending = false;
}
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/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" />
<div id="app">
<v-app id="inspire">
<v-data-table v-model="selected" :headers="headers" :items="desserts" :pagination.sync="pagination" select-all item-key="name" class="elevation-1">
<template v-slot:headers="props">
<tr>
<th>
<v-checkbox :input-value="props.all" :indeterminate="props.indeterminate" primary hide-details #click.stop="toggleAll"></v-checkbox>
</th>
<th v-for="header in props.headers" :key="header.text" #click="changeSort(header.value)">
<v-icon small>arrow_upward</v-icon>
{{ header.text }}
</th>
</tr>
</template>
<template v-slot:items="props">
<tr :active="props.selected" #click="props.selected = !props.selected">
<td>
<v-checkbox :input-value="props.selected" primary hide-details></v-checkbox>
</td>
<td class="text-xs-center">{{ props.item.name }}</td>
<td class="text-xs-center">{{ props.item.calories }}</td>
<td class="text-xs-center">{{ props.item.fat }}</td>
</tr>
</template>
</v-data-table>
<v-container>
<v-layout>
<v-flex xs6 class="mt-5">
<v-btn>Hide by default but show on selected</v-btn>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
Any help will be appreciated. Thank you.

you can use selected.length.
here is a computed you can add
computed: {
showBtn() {
return this.selected.length > 0
}
},
then use showBtn in your template
<v-btn v-if="showBtn">Hide by default but show on selected</v-btn>
You can also just use it inline, but I prefer using computed, because they cache the value, and make the template more readable
new Vue({
el: "#app",
data: () => ({
pagination: {
sortBy: "name"
},
selected: [],
headers: [
{
text: "Dessert (100g serving)",
align: "left",
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
}
]
}),
computed: {
showBtn() {
return this.selected.length > 0
}
},
methods: {
toggleAll() {
if (this.selected.length) this.selected = [];
else this.selected = this.desserts.slice();
},
changeSort(column) {
if (this.pagination.sortBy === column) {
this.pagination.descending = !this.pagination.descending;
} else {
this.pagination.sortBy = column;
this.pagination.descending = false;
}
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<div id="app">
<v-app id="inspire">
<v-data-table v-model="selected" :headers="headers" :items="desserts" :pagination.sync="pagination" select-all item-key="name" class="elevation-1">
<template v-slot:headers="props">
<tr>
<th>
<v-checkbox :input-value="props.all" :indeterminate="props.indeterminate" primary hide-details #click.stop="toggleAll"></v-checkbox>
</th>
<th v-for="header in props.headers" :key="header.text" :class="['column sortable', pagination.descending ? 'desc' : 'asc', header.value === pagination.sortBy ? 'active' : '']" #click="changeSort(header.value)">
<v-icon small>arrow_upward</v-icon>
{{ header.text }}
</th>
</tr>
</template>
<template v-slot:items="props">
<tr :active="props.selected" #click="props.selected = !props.selected">
<td>
<v-checkbox :input-value="props.selected" primary hide-details></v-checkbox>
</td>
<td class="text-xs-center">{{ props.item.name }}</td>
<td class="text-xs-center">{{ props.item.calories }}</td>
<td class="text-xs-center">{{ props.item.fat }}</td>
</tr>
</template>
</v-data-table>
<v-container>
<v-container>
<v-layout>
<v-flex xs6 class="mt-5">
<v-btn v-if="showBtn">Hide by default but show on selected</v-btn>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>

Related

How to sort elements in a column in v-data-table

I have a v-data-table and the elements in the first columns are some true and false values. By clicking the 'sortable' icon in the header I sort these elements in the column. I want to make that when I open the page, the 'true' values to be sorted first. How can I manage this?
headers: [
{
text: '',
sortable: true,
value: 'status',
}]
Html:
<v-data-table
:pagination.sync="pagination"
:headers="headers"
:items="items"
>
<template>
<tr>
<td>
<v-icon v-if="status">
{{status}}
</v-icon>
</td>
</tr>
</template>
</v-data-table>
Values of status are like: True, False, True, False, False
I want to sort the elements of the column as that: True True False False False
Firstly true values and than false.
You can use sort-by and sort-desc
<v-data-table
:pagination.sync="pagination"
:headers="headers"
:items="items"
sort-by="status"
:sort-desc="true"
>
<template>
<tr>
<td>
<v-icon v-if="status">
{{status}}
</v-icon>
</td>
</tr>
</template>
</v-data-table>
You can check more here
You can use external sorting using sortBy and sortDesc:
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: () => ({
headers: [ { text: '', sortable: true, value: 'status' } ],
items: [ { status: "True" }, { status: "False" }, { status: "True" } ],
sortBy: "status",
sortDesc: true
})
});
<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://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<v-app id="app">
<v-data-table
:headers="headers"
:items="items"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
>
<template v-slot:item.status="{ item }">
<tr>
<td>
<v-icon v-if="item.status">{{item.status}}</v-icon>
</td>
</tr>
</template>
</v-data-table>
</v-app>

How can I remove other values ​based on the value I selected?

When using Vuetify v-autocomplete component and using the prop multiple we can multi select values.
How can I remove other values ​​based on the value I selected?
For example:
When I select the main value, the others will be selected removed.Then, when I select the first value, the main value and other values ​​will be deselected. Then when I select the third and others (the third and below are in the same group) the selected main and first value will be selected removed.
<div id="app">
<v-app>
<v-main>
<v-container>
<template>
<v-card color="blue-grey darken-1" dark>
<v-form>
<v-container>
<v-row>
<v-col cols="5">
<v-autocomplete
v-model="parametres"
:items="people"
filled
chips
color="blue-grey lighten-2"
label="Liste"
item-text="name"
item-value="name"
multiple
>
<template v-slot:selection="data">
<v-chip
v-bind="data.attrs"
:input-value="data.selected"
close
#click="data.select"
#click:close="remove(data.item)"
>
{{ data.item.name }}
</v-chip>
</template>
<template v-slot:item="data">
<template v-if="typeof data.item !== 'object'">
<v-list-group>
<v-list-item-content
v-text="data.item"
></v-list-item-content>
</template>
<template v-else>
<v-list-item-content>
<v-list-item-title
v-html="data.item.name"
></v-list-item-title>
</v-list-item-content>
</v-list-group>
</template>
</template>
</v-autocomplete>
</v-col>
</v-row>
</v-container>
</v-form>
<v-divider></v-divider>
</v-card>
</template>
</v-container>
</v-main>
</v-app>
</div>
<script>
new Vue({
el: "#app",
vuetify: new Vuetify(),
data() {
return {
selected: ["name"],
autoUpdate: true,
parametres: ["Main Select"],
people: [
{ name: "Main Select"},
{ name: "First Select"},
{ name: "Second Select"},
{ name: "Third Select."},
{ name: "Fourth Select."},
{ name: "Fifth Select."},
],
model: 1,
};
},
methods: {
remove(item) {
const index = this.parametreler.indexOf(item.name);/*Chip Remove */
if (index >= 0) this.parametreler.splice(index, 1); /*Chip Remove */
},
},
});
</script>
Hi #sercan you can use the #change events and call method on this event and write your logic within that method.
<div id="app">
<v-app>
<v-main>
<v-container>
<template>
<v-card color="blue-grey darken-1" dark>
<v-form>
<v-container>
<v-row>
<v-col cols="5">
<v-autocomplete v-model="parametres" :items="people" filled chips color="blue-grey lighten-2" label="Liste" item-text="name" item-value="name" multiple :key="index">
<template v-slot:selection="data">
<v-chip v-bind="data.attrs" :input-value="data.selected" close #click="data.select" #click:close="remove(data.item)">
{{ data.item.name }}
</v-chip>
</template>
<template v-slot:item="data">
<template v-if="typeof data.item !== 'object'">
<v-list-group>
<v-list-item-content v-text="data.item">
<span>{{typeof data.item !== 'object'}}</span>
</v-list-item-content>
</template>
<template v-else>
<v-list-item-content #click="updateSelection(data.item.name)">
<v-list-item-title v-html="data.item.name"></v-list-item-title>
</v-list-item-content>
</v-list-group>
</template>
</template>
</v-autocomplete>
</v-col>
</v-row>
</v-container>
</v-form>
<v-divider></v-divider>
</v-card>
</template>
</v-container>
</v-main>
new Vue({
el: "#app",
vuetify: new Vuetify(),
data() {
return {
selected: ["name"],
autoUpdate: true,
parametres: ["Main Select"],
people: [
{ name: "Main Select" },
{ name: "First Select" },
{ name: "Second Select" },
{ name: "Third Select." },
{ name: "Fourth Select." },
{ name: "Fifth Select." }
],
model: 1,
index: 0
};
},
methods: {
updateSelection(name) {
let toRemove = ["Main Select","First Select"];
let temp = event;
console.log(name);
switch (name) {
case "Main Select":
this.parametres = ["Main Select"];
this.index++;
break;
case "First Select":
this.parametres = ["First Select"]
this.index++;
break;
default:
this.parametres = this.parametres.filter( ( el ) => !toRemove.includes( el ) );
}
},
remove(item) {
const index = this.parametreler.indexOf(item.name); /*Chip Remove */
if (index >= 0) this.parametreler.splice(index, 1); /*Chip Remove */
}
}
});

Vuetify v-simple-table Highlight Selected Row

Been reading the docs in Vutify for their v-simple-table and v-data-table and I am trying to figure out if there is a way to add a row highlight like you can for a v-data-table.
Such as this?
Vuetify - How to highlight row on click in v-data-table
My table body looks like this:
<v-simple-table dense fixed-header height="90vh" >
<template v-slot:default>
<thead >
<tr >
<th style="font-size: 16px;height: 40px;" width='4%' class="black--text">
Location
</th>
<template v-if="Object.keys(arrAvailableDates).length">
<th style="font-size: 17px; " class="text-center black--text" v-for="(strDate, intIndex) in arrAvailableDates" :key="intIndex">
<span> {{ $moment(strDate).format('D MMM (ddd)') }}</span>
<v-badge tile v-if="total[strDate] > 0" inline color="green" v-bind:content="total[strDate]" > </v-badge>
</th>
</template>
<template v-else>
<th class="text-center" v-for="intHeaderCounter in 6" :key="intHeaderCounter">
<v-skeleton-loader
:key="intHeaderCounter"
type='text'
></v-skeleton-loader>
</th>
</template>
</tr>
</thead>
<tbody v-if="!blnLoading">
<template v-if="Object.keys(arrFiltered).length" >
<tr class="teal lighten-5"
v-for="(arrData, strLocationName) in arrFiltered"
:key="'f-' + strLocationName"
>
<th class="black--text text-darken--3">
{{ strLocationName }} <br/><span class="caption">{{arrData['zip']}}</span>
</th>
<template v-for="(arrAppointmentData, strDate) in arrData['appointment']">
<td :key="strDate" class="text-center ma-0 pa-0" >
<template v-if="typeof(arrAppointmentData) == 'object' ">
<span class="time-slot-x-small" v-for='(intCount, intIndex) in arrAppointmentData' :key="intIndex">
{{ $moment(intIndex, ["HH:mm:ss"]).format('hh:mma')}}
<span class="dot">{{intCount}}</span>
</span>
</template>
<template v-else>
-
</template>
</td>
</template>
</tr>
</template>
I can hover a row and it will show that the row is been hover but I am trying to create a way where if I click on the row, it will change the background color when selected.
An example I am trying to mirror is like this but with a simple table:
https://www.codeply.com/p/hi40H9aug9
Here is a more Vue centric approach...
template:
<tbody>
<tr
v-for="(item,idx) in items"
:key="item.name"
#click="handleClick(idx)"
:class="{ selected: selected.includes(idx) }"
>
<td>{{ item.name }}</td>
<td>{{ item.calories }}</td>
</tr>
</tbody>
script:
data () {
return {
items: [
{
id: 1,
name: "Frozen Yogurt",
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: "1%",
},
],
selected: [],
}
},
methods: {
handleClick(i) {
let pos = this.selected.indexOf(i)
if (pos > -1) {
this.selected.splice(pos, 1);
}
else {
this.selected.push(i)
}
},
}
https://codeply.com/p/PaV3dwWk1j

Using watchers in VueJS?

I am trying to use Watchers in VueJS but having bit of a hard time wrapping my head around them. For example in this case i have set up a watch which checks for the tab i am on and if the tab changes it should reset the selected value back to an empty array. Now i have set the parameters as oldValue and newValue but i am not quite sure how will i use those.
Check this codepen.
Here is the Complete example:-
new Vue({
el: "#app",
data() {
return {
tabs: ["Tab1", "Tab2"],
activeTab: 0,
headers: [{
text: "Dessert (100g serving)",
align: "left",
value: "name"
},
{
text: "Calories",
value: "calories"
}
],
items: [{
name: "Ice cream sandwich",
calories: 237
},
{
name: "Frozen Yogurt",
calories: 159
}
],
selected: []
};
},
methods: {
toggleAll() {
if (this.selected.length) this.items = [];
else this.selected = this.items.slice();
}
},
watch: {
activeTab: (oldValue, newValue) => {
if (oldValue !== newValue) {
this.selected = [];
}
}
}
});
<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" />
<div id="app">
<v-app id="inspire">
<v-tabs fixed-tabs v-model="activeTab">
<v-tab v-for="tab in tabs" :key="tab">
{{ tab }}
</v-tab>
<v-tab-item v-for="tab in tabs" :key="tab">
<v-data-table v-model="selected" :headers="headers" :items="items" select-all item-key="name" class="elevation-1" hide-actions>
<template v-slot:headers="props">
<tr>
<th>
<v-checkbox :input-value="props.all" :indeterminate="props.indeterminate" primary hide-details #click.stop="toggleAll"></v-checkbox>
</th>
<th v-for="header in props.headers" :key="header.text">
<v-icon small>arrow_upward</v-icon>
{{ header.text }}
</th>
</tr>
</template>
<template v-slot:items="props">
<tr :active="props.selected" #click="props.selected = !props.selected">
<td>
<v-checkbox :input-value="props.selected" primary hide-details></v-checkbox>
</td>
<td>{{ props.item.name }}</td>
<td>{{ props.item.calories }}</td>
</tr>
</template>
</v-data-table>
</v-tab-item>
</v-tabs>
</v-app>
</div>
I am not quite sure how i will use that watch so if someone can help me with that, i sure would appreciate it. Thank you.
You're using a fat arrow function for activeTab, it needs to be a normal function or it doesn't have a proper reference to this
Change to this:
activeTab: function (oldValue, newValue) { // function instead of =>
if (oldValue !== newValue) {
this.selected = [];
}
}
Also, there's an issue with your code when you use the check all box.
As a good rule of thumb, all top level functions should be declared using function. Only use => within the functions themselves when a nested function needs access to this

How to show and hide rows in v-data-table Vue.js + Vuetify

I'm new at Vue developer and I make a V-Data-Table consuming a JSON with vue-resource. That´s done already, but now I want to show/hide child rows based on user selection.
e.g.: click on '+' and the table shows the rows, click on '-'and the table hide the rows.
<template>
<v-app>
<div>
<v-flex xs12 sm6 d-flex>
<v-select
v-if="retornoDoJson"
:items="retornoDoJson.nations"
v-model="paisSelecionado"
label="Selecione Um"
v-on:change="selectionChanged"
single-line
menu-props="bottom"
></v-select>
</v-flex>
</div>
<div v-if="paisSelecionado">
<v-data-table :headers="headers" :items="retornoDoJson.top_10s[paisSelecionado]" hide-actions>
<template slot="items" slot-scope="props">
<v-btn fab dark color="indigo">
<v-icon dark>add</v-icon>
</v-btn>
<td class="parent-row">{{ props.item.name }}</td>
<td class="child-row">{{ props.item.club }}</td>
<td class="child-row">{{ props.item.phy }}</td>
<td class="parent-row">{{ props.item.age }}</td>
<td class="parent-row">{{ props.item.pas }}</td>
<td class="child-row">{{ props.item.nationality }}</td>
</template>
</v-data-table>
</div>
</v-app>
</template>
<script>
export default {
data() {
return {
paisSelecionado:undefined,
headers: [
{
text: ' ',
align: 'left',
sortable: false,
value: 'name'
},
{ text: 'name', value: 'name' },
{ text: 'club', value: 'club' },
{ text: 'phy', value: 'phy' },
{ text: 'age', value: 'age' },
{ text: 'pas', value: 'pas' },
{ text: 'nationality', value: 'nationality' }
],
retornoDoJson: []
};
},
methods: {
loadApi() {
this.$http
.get("http://localhost:8080/data.json")
.then(this.successCallback, this.errorCallback);
},
successCallback: function(resposta) {
this.retornoDoJson = resposta.data;
console.log(this.retornoDoJson);
},
selectionChanged: function() {
console.log("selecionarItem:this.selecionarPais:", this.paisSelecionado);
}
},
mounted() {
this.loadApi();
}
};
</script>
<style>
</style>
There's any way to do that?
If I understood you correctly, I hope this helps, also you can check a working example here: https://codepen.io/anon/pen/zemZoB
<template slot="items" scope="props">
<template v-if="props.item.show">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">
<v-btn #click.native="props.item.show = false">
Hide
</v-btn>
</td>
</template>
<template v-else>
<v-btn #click.native="props.item.show = true">
Show
</v-btn>
</template>
</template>

Categories

Resources