Vuetify update select input-value by prepend-item event - vue.js

I'd like to update the select value by clicking the prepended item in a Vuetify select. But the model doesn't update the item-text in the select input.
<v-select
:items="loadedTasks"
v-model="selectedTask"
item-text="text"
item-value="value"
return-object
:menu-props="{closeOnContentClick: true}"
>
<template v-slot:prepend-item>
<v-list-item
#click="selectedTask = {text:'none', value: 'none'}"
>
Text
</v-list-item>
</template>

If you are trying to add some "default" item to the select, the prepend-slot is no way to go as it cannot be "selected". It's better to just add your "default" item directly into the loadedTasks array
For example using computed:
computed: {
tasksToSelect() {
return [{text:'none', value: 'none'}, ...this.loadedTasks]
}
}
...and use it like <v-select :items="tasksToSelect" />

Related

Select All functionality to select filtered items in vuetify combobox

I'm using vuetify combobox and the select all is working as expected as described in How to have a "select all" option on a v-select or v-combobox?.
What I'm trying to achieve is - when I check the Select All, it should select all the filtered values from the list.
In this example, I've typed "Pha..." and what I'm trying to achieve is to get the filtered list to be returned.
The Combobox is as below -
<v-combobox v-if="editedIndex == -1"
label='Phase'
v-model='editedItems.selected_values'
:items='phases'
item-value='pp_code'
item-text='phasedetails'
class="pl-2 pr-2"
multiple
chips
>
<template v-slot:prepend-item>
<v-list-item
ripple
#click="toggle(); editedItems.selected_values.length = phases.length;"
>
<v-list-item-action>
<v-icon :color="editedItems.selected_values.length > 0 ? 'indigo darken-4' : ''">
{{ icon }}
</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
Select All
</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-divider class="mt-2"></v-divider>
</template>
</v-combobox>
The toggle function is as below -
toggle () {
this.$nextTick(() => {
if (this.likesAllFruit) {
console.log("Select all clicked")
this.selectedFruits = []
console.log("Typed value is ")
console.log(this.editedItems.phase_code)
console.log("Selected values ")
console.log(this.editedItems.selected_values)
this.alreadySelectedPhases.push(this.editedItems.selected_values)
console.log(this.alreadySelectedPhases)
console.log(this.phases.length)
} else {
this.editedItems.selected_values = this.phases.slice()
}
})
},
I'm not getting the typed value until the combobox is selected so that we can filter the list by the typed value and return.
Please let me know if anyone has any idea on how we can achieve it. Or if we have any inbuilt method for it.
Thanks in Advance.

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"]

Vuetify datatable search prop with autocomplete component

I'm trying to configure a drop down filter for each column in my vuetify data table. It seems the vuetify autocomplete component has the functionality I want but I'm not sure how to get the values from the autocomplete component to filter the data table. Here's what I have:
<template>
<v-card>
<v-card-title>
{{gridTitle}}
<v-spacer></v-spacer>
</v-card-title>
<v-data-table
v-model="selected"
:headers="headers"
:items="dataSource"
class="elevation-1"
:search="search"
:loading="isloading"
item-key="id"
show-select
multi-sort
dense
>
<template v-slot:header.id="{ header }" >
<v-autocomplete
v-model="search"
:items="dataSource"
item-text="id"
:label="header.value"
v-bind="selected"
dense
multiple
chips
small-chips
filled
>
</v-autocomplete>
</template>
<v-progress-linear
slot="progress"
color="blue"
indeterminate
></v-progress-linear>
<v-alert
slot="no-results"
:value="true"
color="error"
icon="warning"
>Your search for "{{ search }}" found no results.</v-alert>
</v-data-table>
</v-card>
</template>
<script>
export default {
name: "ConfirmationsGrid",
data() {
return {
isloading: true,
search: "",
selected: [],
};
},
props: {
dataSource: {
type: Array[Object],
default: new Array(),
},
headers: Array[String],
gridTitle: String,
},
mounted() {
this.isloading = false;
},
methods: {
onSelectMethod: function (value) {
this.$emit("select_method", value);
},
},
};
</script>
At the moment I'm testing with the one header. slot but I plan on extending to all headers. This renders the autocomplete as the column header and also shows the correct values in the drop down but selecting them doesn't filter the table. I only get the following error:
[Vue warn]: Invalid prop: type check failed for prop "search". Expected String with value "2579034", got Array
Any ideas on how I can convert the autocomplete data into a string?
You are adding the prop multiple to the v-autocomplete tag with v-model search, so it returns an Array, i.e.:
["search option1", "searchOption2"]
But the v-autocomplete tag with v-model selected is using the search prop as String, so that's te reason of the error.
The default behavior of the search prop for v-autocomplete tag is to match the string passed to it with each value in its options.
To test it, remove the multiple prop in the search v-autocomplete tag, and you can see that it works.
Now, in order to work with multiple word search, you can have a computed property as items for the first v-autocomplete:
...
computed: {
itemsForSelected() {
if (this.search.length) {
return this.dataSource.filter(item => this.search.includes(item))
}
return this.dataSource
}
}
...
<template>
<v-card>
<v-card-title>
{{gridTitle}}
<v-spacer></v-spacer>
</v-card-title>
<v-data-table
v-model="selected"
:headers="headers"
:items="itemsForSelected"
class="elevation-1"
:loading="isloading"
item-key="id"
show-select
multi-sort
dense
>
<template v-slot:header.id="{ header }" >
<v-autocomplete
v-model="search"
:items="dataSource"
item-text="id"
:label="header.value"
v-bind="selected"
dense
multiple
chips
small-chips
filled
>
</v-autocomplete>
</template>
<v-progress-linear
slot="progress"
color="blue"
indeterminate
></v-progress-linear>
<v-alert
slot="no-results"
:value="true"
color="error"
icon="warning"
>Your search for "{{ search }}" found no results.</v-alert>
</v-data-table>
</v-card>
</template>
Now you can remove the search prop from the first v-autocomplete, this solution is not useful if you want to have the search by substrings ("hol" matching "alcohol"), it just filter the items from the source that are not selected in the search filter. A better solution could be includes a regex to match more options.

Vuetify Datatable - Rendering element on first row only

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.

Vuejs Vuetify how to access properties of object in v-select

My use case.
I got an array of objects from a back-end api.
I want to render those objects in a v-select
This is my code.
<v-select
:items="categories"
name="category"
label="Select a category"
v-model="category"
v-validate="'required'"
>
</v-select>
But it gives me the output.
But I wants objects name property to be display in the v-select
We would do this in vanilla Vue.js
<li v-for="cat in categories" :key="cat.name">{{cat.name}}</li>
But here with vuetify we can't do this.
:items="categories.name"
Vuetify documentation
Can be an array of objects or array of strings. When using objects,
will look for a text and value field. This can be changed using the
item-text and item-value props.
What they actually mean by item-text and item-value
How do I achieve this using item-text
Your category has name attribute, you can pass to item-text:
<v-select
:items="categories"
v-model="category"
name="category"
v-validate="'required'"
item-text="name"
label="Select a category"
/>
I'd seen a similar solution on an example on codepen, but for some reason it did not work to merely assign the "name" to my item-text. Adding single quotes around the name attribute, thus making it a string, is what worked for me (but I don't know why that is):
<v-select v-if="categories"
:items="categories"
:item-text="'name'"
:item-value="'name'"
v-model="selectedCategory"
name="selectedCategory"
label="Select categories"
solo
dark
>
</v-select>
<script> ...
categories: [
{ name: "test", path: "test" },
{ name: "test1", path: "test1" }
],
</script>
For those still looking, the item-name and item-value props are used to specify what value to return for the name and value from the item. If you want to display only the name, but keep the entire object as the value, the return-object prop will return the entire object in the v-model.
Check out the documentation at: https://vuetifyjs.com/en/components/selects/#custom-text-and-value
<v-select :items="categories" v-model="category" name="category"
v-validate="'required'" item-text="name" return-object label="Select a category"
/>
For Vuetify 2.x use <v-slot:item> slot to customize the list and <v-slot:selection> to customize the selection. check v-select slot list in the docs
<v-select
:items="categories"
name="category"
label="Select a category"
v-model="category"
v-validate="'required'"
>
<template v-slot:item="{item}">
{{item.name}}
</template>
<template v-slot:selection="{item}">
{{item.name}}
</template>
</v-select>
To be clear here's with script
<template>
<v-select
outlined
:items="areas"
v-model="area"
name="area"
item-text="text"
label="Area"
return-object
></v-select>
</template>
<script>
export default {
data: () => ({
area: { text: 'area', disabled: false, status: false },
areas: [
{ text: 'Pre-op', disabled: false },
{ text: 'Operational', disabled: false },
{ text: 'USDA', disabled: false },
],
}),
}
</script>