How to get the value of a Vuetify Select? - vue.js

I have a vuetify select (v-select):
<v-select prepend-icon="local_shipping" :rules="[v => !!v || 'Es necesario asignarl el T.A.R.']" required label="T.A.R." v-model="editedItem.tarID" :items="tars" item-text="nombre" item-value="id"></v-select>
What i want to do is get the value of the id in edit mode, that is, in this way:
I have been following the official documentation of vuetify to edit an item of a table in a modal dialog.
Just as the inputs have assigned text, I would also like the select to have its assigned data.
Here is what i have:
The edit button:
<v-btn icon class="mx-0" #click="editItem(props.item)">
<v-icon color="info">mode_edit</v-icon>
</v-btn>
The editedItem and the defaultItem, just like the official documentation:
editedItem: {
entidadID: "",
numeroEstacion: "",
tarID: "",
clave: "",
id:""
},
defaultItem: {
entidadID: "",
numeroEstacion: "",
tarID: "",
clave: "",
id: ""
},
The way in which i populate the v-select in data:
tars: [
{
id: "",
nombre: ""
}
],
I populate my tables like this:
<v-data-table
:headers="headers"
:items="items"
hide-actions
class="slideInDown"
:search="search"
:id="items.id"
>
<template slot="items" slot-scope="props">
<td>{{ props.item.grupo }}</td>
<td class="text-xs-right">{{ props.item.numeroEstacion}}</td>
<td class="text-xs-right">{{ props.item.clave }}</td>
<td class="text-xs-right">{{ props.item.nombre }}</td>
<td class="text-xs-right">{{props.item.id}}</td>
<td class="justify-center layout px-0">
<v-btn icon class="mx-0" #click="editItem(props.item)">
<v-icon color="info">mode_edit</v-icon>
</v-btn>
<v-btn icon class="mx-o" #click="deleteItem(props.item)">
<v-icon color="red">delete_sweep</v-icon>
</v-btn>
</td>
</template>
<v-alert slot="no-results" :value="true" color="error" icon="warning">
Tu búsqueda para "{{search}}" no arrojó resultados.
</v-alert>
</v-data-table>
And the editItem button:
editItem(item) {
this.editedIndex = this.items.indexOf(item);
this.editedItem = Object.assign({}, item);
this.dialog = true;
},
The editedIndex equals -1 in data return. So when i touch New Item button editedIndex = -1, when i touch The edit button, editedIndex != -1, like the documentation
The link of the official documentation:
https://vuetifyjs.com/en/components/data-tables
Here is my PUT method:
if(this.editedIndex > -1){
axios({
headers:{
"Authorization": "Bearer "+localStorage.getItem('token')
},
method: "put",
url: "http://localhost:58209/api/PutEstacion",
data:{
NumeroEstacion: this.editedItem.numeroEstacion,
Clave: this.editedItem.clave,
**TarID: this.editedItem.tarID**,
ID: this.editedItem.id,
}
}).then(response => {
console.log(response);
this.snackbar = true;
this.textSnackbar = "La información ha sido actualizada correctamente";
this.dialog = false
}).catch(error =>{
console.log(error.response);
this.snackbar = true;
this.textSnackbar = "Lo sentimos ha ocurrido un problema actualizando la informacíón";
this.dialog = false
});
}
This line: TarID: this.editedItem.tarID has no value. So i can't put in my WebApi. And finally my WbApi:
var ID = _context.Estacion.Where(x => x.ID == putEstacionDTO.ID).Select(x => x.ID).FirstOrDefault();
var NumeroEstacion = putEstacionDTO.NumeroEstacion;
var Clave = putEstacionDTO.Clave;
var TarID = putEstacionDTO.TarID;
var putEstacion = _context.LoadStoredProc("PutEstaciones")
.WithSqlParam("p0", NumeroEstacion)
.WithSqlParam("p1", Clave)
.WithSqlParam("p2", TarID)
.WithSqlParam("p3", ID)
.ExecuteStoredProc<PutEstacionDTO>();
return Ok();
When i debugging only the 'select' = 0 (TarID).
EDIT, Add the :items="items" of datatable
Data:
items: [
{
id: "",
grupo: "",
numeroEstacion: "",
clave: "",
nombre: "",
}
],
Method to set the items:
axios
.get("http://localhost:58209/api/GetEstaciones", {
headers: {
Authorization: "Bearer " + localStorage.getItem("token")
}
})
.then(response => {
console.log(response);
this.items = response.data;
this.snackbar = true;
this.textSnackbar = "Se han cargado correctamente las estaciones";
})
.catch(error => {
console.log(error.response);
this.snackbar = true;
this.textSnackbar =
"Lo sentimos, no pudimos cargar la información de los tanques";
});

Related

What can I do to replace a button in place of another in vuetify?

I need replace a button when it's clicked because I need that button to have 3 states (entrada, salida and registrado),I already have those buttons but they only work when reloading the page, I just want it to render without reload, I add my code for a better explanation
vuetify-data-table
<td>
<v-btn color="success" v-if="item.check_in == null && item.check_out == null"
v-on:click="entrada(item)">
Entrada</v-btn>
<v-btn color="error" v-else-if="item.check_out == null && item.check_in !== null"
v-on:click="salida(item)">
Salida</v-btn>
<v-btn v-else disabled>Registrado</v-btn>
</td>
You can play out with the buttons with in the <v-data-table> without any page refresh.
Live Demo :
new Vue({
el: '#app',
data () {
return {
headers: [
{
text: 'Check-In',
value: 'checkin'
},
{ text: 'Check-Out', value: 'checkout' },
{ text: 'Actions', value: 'action' }
],
details: [
{
checkin: null,
checkout: null,
action: null
},
{
checkin: 1,
checkout: null,
action: null
},
{
checkin: 1,
checkout: 3,
action: null
}
]
}
},
methods: {
entrada(index) {
this.details.forEach((obj, i) => {
if (i === index) {
obj.checkin = 2
}
})
},
salida(index) {
this.details.forEach((obj, i) => {
if (i === index) {
obj.checkin = null,
obj.checkout = null
}
})
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.7/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vuetify#1.5.7/dist/vuetify.min.css"/>
<div id="app">
<v-app id="inspire">
<div>
<v-data-table
:headers="headers"
:items="details"
class="elevation-1"
>
<template v-slot:items="{item, index}">
<td>{{ item.checkin }}</td>
<td>{{ item.checkout }}</td>
<td>
<v-btn color="success" v-if="item.checkin == null && item.checkout == null"
v-on:click="entrada(index)">
Entrada</v-btn>
<v-btn color="error" v-else-if="item.checkout == null && item.checkin !== null"
v-on:click="salida(index)">
Salida</v-btn>
<v-btn v-else disabled>Registrado</v-btn>
</td>
</template>
</v-data-table>
</div>
</v-app>
</div>

Hide no-data template until after data loads via Axios

I have a typical Vue data-table with a template section that displays an alert if no records are found. Problem is, that displays right away, even before my Axios method has a chance to go out and get records.
How can I prevent the flash of red warning message before the actual data loads?
<template>
<div>
<v-card>
<v-card-title>
<h1>Locations</h1>
</v-card-title>
<v-data-table :headers="headers" :items="locations" :search="search" :fixed-header="true" :loading="true" class="elevation-1">
<template v-slot:items="location">
<td>{{ location.item.id }}</td>
<td>{{ location.item.company }}</td>
<td>{{ location.item.category }}</td>
<td>{{ location.item.name }}</td>
<td>{{ location.item.city }}, {{ location.item.state }}</td>
</template>
<template v-slot:no-data>
<v-alert :value="true" color="error" icon="warning">Sorry, no locations found.</v-alert>
</template>
</v-data-table>
</v-card>
</div>
</template>
<script>
import { HTTP } from "#/utils/http-common";
export default {
name: 'LocationsList',
data() {
return {
headers: [
{ text: "Id", value: "id" },
{ text: "Company", value: "company" },
{ text: "Category", value: "category" },
{ text: "Name", value: "name" },
{ text: "City, State", value: "city" },
],
locations: [],
errors: []
};
},
created: function() {
this.getAllLocations();
},
methods: {
getAllLocations() {
HTTP.get("locations")
.then(response => {
this.locations = response.data;
})
.catch(err => {
this.errors.push(err);
});
},
}
};
</script>
Add a loading state to data, and set it to true
Set the loading state when the call is finished (.finally promise)
Set the v-if on in your template to show when it's not anymore loading
See code below.
<template>
<div>
<v-card>
<v-card-title>
<h1>Locations</h1>
</v-card-title>
<v-data-table :headers="headers" :items="locations" :search="search" :fixed-header="true" :loading="true" class="elevation-1">
<template v-slot:items="location">
<td>{{ location.item.id }}</td>
<td>{{ location.item.company }}</td>
<td>{{ location.item.category }}</td>
<td>{{ location.item.name }}</td>
<td>{{ location.item.city }}, {{ location.item.state }}</td>
</template>
<template v-slot:no-data>
<v-alert v-if="!loading" :value="true" color="error" icon="warning">Sorry, no locations found.</v-alert>
</template>
</v-data-table>
</v-card>
</div>
</template>
<script>
import { HTTP } from "#/utils/http-common";
export default {
name: 'LocationsList',
data() {
return {
headers: [
{ text: "Id", value: "id" },
{ text: "Company", value: "company" },
{ text: "Category", value: "category" },
{ text: "Name", value: "name" },
{ text: "City, State", value: "city" },
],
locations: [],
errors: [],
loading: true
};
},
created: function() {
this.getAllLocations();
},
methods: {
getAllLocations() {
HTTP.get("locations")
.then(response => {
this.locations = response.data;
})
.catch(err => {
this.errors.push(err);
})
.finally(() => {
this.loading = false;
})
},
}
};
</script>

Vuetify datatable watch does not trigger

The function "change sort" executed on header item click does not trigger watch, which fetches updated data from server. On the other hand, if I try to execute fetchRecords method at the end of changeSort method, watch gets triggered multiple times
I need to use Vuetify datatables with server side pagination and sorting, and templates for header and items. I implemented code similarly to Vuetify examples: "Paginate and sort server-side" and "Slot: items and headers" from documentation https://vuetifyjs.com/en/components/data-tables#api.
<template>
<v-card class="table-container">
<v-card-title>
<v-text-field
v-model="searchField"
#blur="fetchRecords()"
#keyup.enter="fetchRecords()"
/>
</v-card-title>
<v-data-table
:headers="headers"
:items="applications.applications"
:loading="paginationLoading"
:pagination.sync="pagination"
:total-items="pagination.totalItems"
no-data-text="No results"
>
<template v-slot:headers="props">
<tr>
<th colspan="4">Dane kandydata</th>
<th colspan="4">Dane polecającego</th>
<th colspan="2">Inne</th>
</tr>
<tr>
<th
v-for="header in props.headers"
:key="header.value"
:class="['column',
header.sortable !== false ? 'sortable' : '' ,
pagination.descending ? 'desc' : 'asc',
header.value === pagination.sortBy ? 'active' : '']"
#click="changeSort(header.value, header.sortable)"
>
{{ header.text }}
<v-icon v-if="header.sortable !== false" small>fas fa-sort-up</v-icon>
</th>
</tr>
</template>
<template v-slot:items="props">
<td>{{ props.item.candidateName }}</td>
<td>{{ props.item.candidateSurname }}</td>
<td>{{ props.item.candidateEmail }}</td>
<td>{{ props.item.candidatePhone }}</td>
<td>{{ props.item.referrerName }}</td>
<td>{{ props.item.referrerSurname }}</td>
<td>{{ props.item.referrerEmail }}</td>
<td>{{ props.item.referrerPhone }}</td>
<td class="text-md-center">
<div>
<v-icon>check_circle_outline</v-icon>
</div>
</td>
<td class="text-md-center">
<div>
<v-icon>check_circle_outline</v-icon>
</div>
</td>
</template>
<v-alert v-slot:no-results :value="true" color="error" icon="warning">
Your search for "{{ searchField }}" found no results.
</v-alert>
</v-data-table>
</v-card>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
data () {
return {
announcementId: '',
announcementTitle: '',
searchField: '',
headers: [
{ text: 'Imię', value: 'candidateName' },
{ text: 'Nazwisko', value: 'candidateSurname' },
{ text: 'Email', value: 'candidateEmail', sortable: false },
{ text: 'Telefon', value: 'candidatePhone' },
{ text: 'Imię', value: 'referrerName' },
{ text: 'Nazwisko', value: 'referrerSurname' },
{ text: 'Email', value: 'referrerEmail', sortable: false },
{ text: 'Telefon', value: 'referrerPhone' },
{ text: 'Status', value: 'processed' },
{ text: 'Akcje', value: 'actions', sortable: false },
],
pagination: {
page: 1,
rowsPerPage: 10,
totalItems: 10,
sortBy: '',
descending: false,
},
paginationLoading: false
}
},
computed: {
...mapState([
'applications',
])
},
watch: {
pagination: {
handler(newVal, oldVal){
if(newVal != oldVal){
this.fetchRecords()
}
},
deep: true
}
},
methods: {
...mapActions([
'getApplications',
]),
fetchRecords () {
this.paginationLoading = true
this.getApplications({
announcementId: this.announcementId,
pagination: this.pagination,
search: this.searchField
})
.then(
response => {
this.paginationLoading = false
if(this.pagination.totalItems != response.totalItems) this.pagination.totalItems = response.totalItems
}
)
.catch(
err => {
console.log(err);
}
)
},
changeSort (columnValue, sortable) {
if(sortable === false){
return
}
if (this.pagination.sortBy === columnValue) {
this.pagination.descending = !this.pagination.descending
console.log(this.pagination.descending);
} else {
this.pagination.sortBy = columnValue
this.pagination.descending = false
}
},
editTableItem(item){
console.log(item);
},
onClearSearch() {
this.searchField = ''
this.fetchRecords()
},
}
}
</script>
You should create new object when changing pagination object. Here I use ES6 syntax:
changeSort (columnValue, sortable) {
if(sortable === false){
return
}
if (this.pagination.sortBy === columnValue) {
this.pagination = {
...this.pagination,
descending: !this.pagination.descending
}
console.log(this.pagination.descending);
} else {
this.pagination = {
...this.pagination,
sortBy: columnValue,
descending: false
}
}
}

how to populate v-text-field with json data

I have a table populated with json data. There is a column 'edit' in every row. When I click on edit a dialog opens up with a form. I want to edit the table data in the form. The value of input fields of the form should show the json data. But it's not showing.
I tried fill up the form using v-model="editedItem.type".
This is my table:
<v-data-table
:items="myjson">
<template v-slot:items="props">
<td>{{ props.item.ApplicationType }}</td>
<td>{{ props.item.ApplicationID }}</td>
<td>
{{props.item.APIToken}}
</td>
<td>{{ props.item.ApplicationName }}</td>
<td >
<img src="edit.svg" #click="editItem(props.item)"> Edit
</td>
</template>
</v-data-table>
This is my json data
{
"Applications": [{
"ApplicationID": "74382DOD",
"ApplicationName": "OIMInstance2",
"ApplicationType": "OIM",
"APIToken": "ZM8R4FRiZWWKbl235u06zbArCdOBPlEKhqHQO8Y9RJ2HgBPC+cZgbIli8fFuNZaey/2tJciJuILIWIn24WTjGA=="
}, {
"ApplicationID": "943ODA6G",
"ApplicationName": "LDAPInstance2",
"ApplicationType": "LDAP",
"APIToken": "R9lDEW5dnN6TZg2sefEEzS6LWMNmFh4iLHMu47LmAsusHl0bZuh2rktSlXqSZRdHHEWq7sP4Xsdy6xNtDYE8xw=="
}]
}
This is my form:
<v-text-field v-model="editedItem.type" label="Type"></v-text-
<v-text-field v-model="editedItem.id" label="ID"></v-text-field>
<v-text-field v-model="editedItem.tok" label="API Token"></v-text-field>
<v-text-field v-model="editedItem.name" label="Name"></v-text-field>
This is my script:
import json from '../../static/mockdata.json'
data: () => ({
myjson: [],
dialog: false,
editedIndex: -1,
editedItem: {
type: '',
id: '',
tok: '',
name: ''
}
},
created () {
this.myjson = json.Applications
},
methods: {
editItem (item) {
this.editedIndex = json.Applications.indexOf(item)
this.editedItem = Object.assign({}, item)
this.dialog = true
}
}
The problem is that you use non-existent keys for the form fields (type, id, tok, name). Try this:
<v-text-field v-model="editedItem.ApplicationType" label="Type"></v-text-field>
<v-text-field v-model="editedItem.ApplicationID" label="ID"></v-text-field>
<v-text-field v-model="editedItem.APIToken" label="API Token"></v-text-field>
<v-text-field v-model="editedItem.ApplicationName" label="Name"></v-text-field>
[ https://jsfiddle.net/2qawL6cg/ ]

How to pull data from a Vuetify Datatable selected row

I have a Vuetify Datatable
<v-data-table
:headers="headers"
:items="members"
item-key="id"
v-model="selected"
:search="search"
>
<template slot="items" slot-scope="props">
<tr :active="props.selected" #click="select(props.item)">
<td>{{ props.item.name }}</td>
<td class="text-xs-right">{{ props.item.FirstName}}</td>
<td class="text-xs-right">{{ props.item.LastName }}</td>
<td class="text-xs-right">{{ props.item.email }}</td>
<td class="text-xs-right">{{ props.item.department}}</td>
<td class="text-xs-right">{{ props.item.division}}</td>
</tr>
</template>
And when I select a row I want to be able to populate an Item on the same page with some of the data such as the name and email in a v-card. I currently have
{{msg}}
and in my script I have
return {
msg: "",
then
select(selectedItem) {
this.selected = [];
this.members.forEach(item => {
if (item.id == selectedItem.id) {
this.selected.push(item);
this.msg = selectedItem.FirstName;
}
});
},
I need to put name into the msg. I feel that I'm going the long way around to get my data and was wondering if someone has a better solution. Thanks for the support.
<v-data-table #click:row="rowClick" item-key="name" single-select ...
methods: {
rowClick: function (item, row) {
row.select(true);
//item - selected item
}
}
<style>
tr.v-data-table__selected {
background: #7d92f5 !important;
}
</style>
or
<style scoped>
/deep/ tr.v-data-table__selected {
background: #7d92f5 !important;
}
</style>
Example
https://codepen.io/nicolai-nikolai/pen/GRgLpNY
Since there is a binding between the data table and this.selected, you only need to populate msg as a computed property of the component. You don't need to manually add to this.selected by listening to the click event.
computed: {
msg() {
const selectedRow = this.selected[0];
return selectedRow ? `${selectedRow.firstName} ${selectedRow.lastName}` : "no data selected";
}
}
EDIT
I've added a minimal example. Note for the item-key prop of v-data-table, you should use unique values.
<template>
<v-card>
<v-card-text>
<v-data-table :headers="headers" :items="members" v-model="selected" item-key="id">
<template slot="items" slot-scope="props">
<td>
<v-checkbox
v-model="props.selected"
:disabled="!props.selected && selected.length != 0"
:indeterminate="!props.selected && selected.length != 0"
></v-checkbox>
</td>
<td>{{ props.item.firstName}}</td>
<td>{{ props.item.lastName }}</td>
</template>
</v-data-table>
{{ msg }}
</v-card-text>
</v-card>
</template>
<script>
export default {
data() {
return {
headers: [
{ text: "Select", value: "id", sortable: false },
{ text: "First Name", value: "firstName", sortable: true },
{ text: "Last Name", value: "lastName", sortable: true }
],
selected: [],
members: [
{
id: 1,
firstName: "a",
lastName: "b"
},
{
id: 2,
firstName: "x",
lastName: "y"
}
]
};
},
computed: {
msg() {
const selectedRow = this.selected[0];
return selectedRow ? `${selectedRow.firstName} ${selectedRow.lastName}` : "no data selected";
}
}
};
</script>