Vuetify Datatable - Rendering element on first row only - vue.js

i have a problem on a vue project of mine.
i have a vuetify datatable that receives data from a .net core backend with mongo.
it works just fine and every row have a edit and delete buttons. but in this case i need to limit edit and delete buttons to show only on the first row of the datatable.
i've tried a lot of solutions from the internet but none of them worked for me so far.
here's the code for the datatable and the buttons, respectively:
<v-data-table
:headers="headers"
:items="pacientes"
:search="search"
:page.sync="page"
:items-per-page="itemsPerPage"
hide-default-footer
sort-by="status"
class="elevation-1"
#page-count="pageCount = $event"
>
<template
v-slot:item.edit="{ item }" >
<v-btn
color="blue"
tile
x-large
icon
#click="aprovar(item.nomePaciente, item.idEspera, item.matricula)"
>
<v-icon>mdi-pencil-circle</v-icon>
</v-btn>
</template>
<template
v-slot:item.delete="{ item }"
>
<v-btn
color="red"
x-large
tile
icon
#click="abrirModalDeletar(item.nomePaciente, item.idEspera)">
<v-icon>mdi-delete-circle</v-icon>
</v-btn>
</template>
Any help would be appreciated, thanks!

You could introduce a boolean property to your items in the array, let's call it isFirst Then you could listen to the event of current-items in the data table, which returns the current items in view. And based on that, show the buttons for the first row. So I suggest the following:
<v-data-table #current-items="setFirst" ...... >
And the function:
methods: {
setFirst: function(currItems) {
// first check that actually exists values
if (currItems.length) {
// toggle all to false
currItems.forEach(x => x.isFirst = false)
// just set first to true
currItems[0].isFirst = true;
}
}
},
and then set an v-if to the buttons:
<v-btn v-if="item.isFirst" ....>
CODEPEN

If your object has an ID and you know what that ID is, you can set a v-if statement for your edit and delete buttons to only render when the ID is equal to that value. Something like this:
<template
v-slot:item.edit="{ item }" >
<v-btn
color="blue"
tile
v-if="item.id===1"
x-large
icon
#click="aprovar(item.nomePaciente, item.idEspera, item.matricula)"
>
<v-icon>mdi-pencil-circle</v-icon>
</v-btn>
</template>
<template
v-slot:item.delete="{ item }"
>
<v-btn
color="red"
x-large
tile
v-if="item.id===1"
icon
#click="abrirModalDeletar(item.nomePaciente, item.idEspera)">
<v-icon>mdi-delete-circle</v-icon>
</v-btn>
</template>
If your item doesn't have an ID, when you fetch your data, you can programmatically set a property on the first item and then use the v-if statement on that property.
Something like:
fetchData().then(items => {
if (items.length >= 1) {
items[0].showEditDelete = true
}
})
Then your v-if statement will look like v-if=item.showEditDelete.

Related

Vue show next 10 items when press button

I'm trying to do load more function. When load more button is clicked show next 10 hidden items in v-for allCategories loop.
<template v-for="(category, i) in allCategories">
<v-col :key="i" v-show="i <= 10" class="col-6 col-sm-4">
<v-checkbox
dense
color="black"
:label="category.title"
:value="isCategoryChecked(category.id)"
#click="() => selectCategory(category.id)"
/>
</v-col>
</template>
load more button
<v-btn color="black white--text"
#click="showMoreCategories"
:loading="loading">
{{ $t('general.loadMore') }}
</v-btn>
showMoreCategories function
showMoreCategories() {
}
How do i implement this?
Assuming your variable allCategories contains all the categories you could possibly want (i.e. you don't have to fetch additional categories from a server or local store) then you can replace v-show="i <= 10" with v-show="i <= numberOfCategoriesToShow". Where numberOfCategoriesToShow is a new variable you have defined and initially set to 10.
Then your showMoreCategories function would look like this
showMoreCategories() {
this.numberOfCategoriesToShow += 10;
}

How can I pass a v-data-table row information to child element

I have creating a list of users want to add them tags. I am using a data-table to display them and a combo box using chips to add or remove tags. How can I pass the user information to the method called when I add / remove a tag? Here is my code:
<v-data-table :headers="headers" :items="usersInfos" :search="search" :items-per-page="-1">
<template v-slot:[`item.tags`]="{ item }">
<v-combobox v-model="item.tags" :items="roles" chips clearable label="RĂ´les" multiple>
<template v-slot:selection="{ attrs, item, select, selected }">
<v-chip
v-bind="attrs"
:input-value="selected"
close
#click="select"
#click:close="removeRole(item)"
>
{{ item }} <!-- the tag -->
</v-chip>
</template>
</v-combobox>
</template>
</v-data-table>
Don't know if I understood it correctly but you can do following pass your item with your click event to your methods - call the function and use the passed parameter there.
in your template
#click=getSelectedItem(usersInfos)
in your script
methods: {
getSelectedItem(usersInfos) {
//do code here
console.log(usersInfos)
}
}
and than you have to use this where you have written your child element:
<child :usersInfo="usersInfo">
and in your child.vue you have to set props in your script like this:
props: ["usersInfo"]

How to clear only selected row in data-table, vuetify [duplicate]

This question already has an answer here:
How to clear selected row in v-data-table, Vuetify
(1 answer)
Closed 2 years ago.
I have a vue app where Im using v-data table with show-select option. I want to clear only selected data using "cancel" button and Im looking for solution how to do it correctly. Already I can clear all data from table onclick.
Example on picture:
I want to clear only selected row(Ice cream sandwich)
Here is my code:
Table:
<v-data-table
v-model="selected"
:headers="headers"
:items="desserts"
:single-select="singleSelect"
item-key="name"
show-select
class="elevation-1"
>
<template v-slot:top>
<v-switch
v-model="singleSelect"
label="Single select"
class="pa-3"
></v-switch>
</template>
</v-data-table>
"cancel" button
<v-btn class="ma-2" color="primary" #click="cancel"> Cancel </v-btn>
script
cancel() {
this.desserts = [];
},
Use any unique property (in this example - an id) to filter the row out of your items array.
cancel(){
this.desserts = this.desserts.filter((e)=> {
return e.id !== this.selected.id;
});
}

how to handle a dropdown visibility manually instead of Vuetify controls this

I have created a dropdown menu in vuetify which looks like this:
[![enter image description here][1]][1]
`
<v-menu offset-y>
<template v-slot:activator="{ on }">
<v-btn text v-on="on">
Details
</v-btn>
</template>
<v-list>
<v-list-item>
<v-form ref="form">
<v-radio-group v-model="metrics" required>
<v-radio
label="ABC"
value="abc"
></v-radio>
<v-radio label="XYZ" value="xyz"></v-radio>
</v-radio-group>
<v-divider></v-divider>
<v-radio-group v-model="order" required>
<v-radio
label="Higher"
value="higher"
></v-radio>
<v-radio
label="Lower"
value="lower"
></v-radio>
</v-radio-group>
<v-divider></v-divider>
<v-btn
#click="
sortTableData(
metrics,
order,
$props.tableItems
)
"
>
Apply
</v-btn>
</v-form>
</v-list-item>
</v-list>
</v-menu>`
however,
when I click the Dropdown and select for eg:Installs, the menu
closes..
I have to click the Dropdown again to choose higher/lower..
and the menu closes again..
And again I have to click the Dropdown to Click "Apply" button.
Question : Is there Any way I can hold this menu until I click "Apply"?
Thanks a lot in advance for your help !
Ok, the idea here is to manually handle the dropdown visibility instead of letting Vuetify controls this.
To do so, you need to:
add a :close-on-content-click="false" on your <v-menu> (doc)
add a v-model directive binded to a "data" boolean value (ex: v-model="isDropdownDisplayed"), initialized to false (closed dropdown at load)
The first prop tells Vuetify to not close the dropdown when clicking on content (only an outside click will do it), while the second prop is linking the dropdown visilibity to your custom data boolean value.
As your "data" boolean value is initialized to false (closed dropdown) and is automatically updated to true via the v-model when opening the dropdown, the left thing to do is to pass this value to false on your sortTableData method.
Assuming you're using SFC (but the approach is the same for pure JS components):
Template
<v-menu offset-y :close-on-content-click="false" v-model="isDropdownDisplayed">
...
</v-menu>
Script
{
name: 'MyComponent',
data: function () {
return {
isDropdownDisplayed: false
}
},
methods: {
sortTableData: function (/* args */) {
// ...
this.isDropdownDisplayed = false
// ...
}
}
}

Using Vuetify tooltip (v-tooltip) component with an external activator (i.e. not wrapped)

I understand how to use Vuetify's v-tooltip with the tooltip wrapping the component. However, I'm not quite sure how to have the activator button outside.
e.g. I have this (non-working code):
<v-tooltip bottom
:activator="$refs.filterBtn"
>
Filter displayed items
</v-tooltip>
<v-btn
ref="filterBtn"
icon
#click="isFilter = !isFilter"
>
<v-icon>fa-filter</v-icon>
</v-btn>
I also tried using prop activator without the v-bind:, same result
Idea: I want the button to be placed separately from tooltip in order to run unit tests. When testing, shallowMount strips anything inside <v-tooltip> so I can't test the button. The problem is I don't know how to make tooltip show up on hover (just like it does when wrapped), I do not want to trigger it with #click.
EDIT: here's codepen
How about using the v-hover UI Component. Wrap it around your button. Bind a boolean variable to the v-hover using v-model, call it buttonHovering. Then bind a boolean variable to the v-tooltip using v-model, call it showToolTip. Then use a watcher to toggle showToolTip true and false based on the value of buttonHovering. Or you can make showToolTip a computed property that always returns the value of buttonHovering. Lastly, bind the disabled attribute of the v-tooltip to the !buttonHovering property to ensure that the tooltip only displays when hovering over the button and not the tooltip's activator.
new Vue({
el: '#app',
data () {
return {
buttonHovering: false,
showToolTip: false
}
},
watch: {
buttonHovering (newVal) {
this.showToolTip = newVal
}
}
})
<link href='https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons' rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.16/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-card>
<v-card-title>
<v-hover v-model="buttonHovering">
<v-btn large>
Hello
</v-btn>
</v-hover>
<v-spacer></v-spacer>
<v-tooltip left v-model="showToolTip" :disabled="!buttonHovering">
<span>Hi from over here!</span>
</v-tooltip>
</v-card-title>
</v-card>
</v-app>
</div>
Try this:
<v-tooltip bottom
v-model="filterBtnTTip"
>
Filter displayed items
</v-tooltip>
<v-btn
icon
#click="isFilter = !isFilter"
#mouseover="filterBtnTTip = true"
#mouseleave="filterBtnTTip = false"
>
<v-icon>fa-filter</v-icon>
</v-btn>
...
data () {
return {
...
filterBtnTTip: false
}
}
<v-app>
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn
v-on="on"
>
Your button
</v-btn>
</template>
<span> Your hover message </span>
</v-tooltip>
</v-app>
In my case, it was necessary to place the tooltip together with the button in one component (a custom button with a tooltip function). Therefore, I used a prop activator and added the tooltip itself directly to the button:
<template>
<v-btn
:id="id"
>
<span>
<slot></slot>
<v-tooltip
v-if="tooltipText"
:activator="`#${id}`"
top
>
{{ tooltipText }}
</v-tooltip>
</span>
</v-btn>
</template>
<script>
let id = 0;
export default {
data() {
return {
id: `custom-button-${id++}`, //This is how we get a unique id for each created button
}
}
}
</script>
According to the same scheme, you can place v-tooltip anywhere, the main thing is that at the time of mounting the "activator" already exists.