Hi i want to filter and sor a table in vue js. I do this but when i text in the textbox the letter that i want to search the table is empty. I want to filter the rows and display the ones that matches whatever is in this input. I hope I am making sense. I do not know how to proceed from here. Cookies and a big thank you to anyone who helps!
<script>
import axios from 'axios'
export default {
name: 'Utenti',
data() {
return {
utenti: [],
modalTitle: '',
UtenteTessera: 0,
UtenteNome: '',
UtenteCognome: '',
UtenteEmail: '',
UtenteTelefono: '',
UtenteNomeFilter: '',
UtenteTesseraFilter: '',
utentiWithoutFilter: [],
}
},
methods: {
refreshData() {
axios.post('https://localhost:7285/Utenti/GetDati').then((response) => {
this.utenti = response.data.prova
this.utentiWithoutFilter = response.data.prova
})
},
FilterFn() {
const UtenteTesseraFilter = this.UtenteTesseraFilter
const UtenteNomeFilter = this.UtenteNomeFilter
this.utenti = this.utentiWithoutFilter.filter(function (el) {
return (
el.UtenteTessera.toString()
.toLowerCase()
.includes(UtenteTesseraFilter.toString().trim().toLowerCase()) &&
el.UtenteNome.toString()
.toLowerCase()
.includes(UtenteNomeFilter.toString().trim().toLowerCase())
)
})
},
sortResult(prop, asc) {
this.utenti = this.utentiWithoutFilter.sort(function (a, b) {
if (asc) {
return a[prop] > b[prop] ? 1 : a[prop] < b[prop] ? -1 : 0
} else {
return b[prop] > a[prop] ? 1 : b[prop] < a[prop] ? -1 : 0
}
})
},
},
}
</script>
<template>
<div>
<table >
<thead>
<tr>
<th>
<div >
<input
v-model="UtenteTesseraFilter"
placeholder="Filter"
@keyup="FilterFn()"
/>
<button
type="button"
@click="sortResult('UtenteTessera', true)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5a.5.5 0 0 1 1 0z"
/>
</svg>
</button>
<button
type="button"
@click="sortResult('UtenteTessera', false)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 16a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2zm6.5-4.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 1 0z"
/>
</svg>
</button>
</div>
Tessera
</th>
<th>
<div >
<input
v-model="UtenteNomeFilter"
placeholder="Filter"
@keyup="FilterFn()"
/>
<button
type="button"
@click="sortResult('UtenteNome', true)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5a.5.5 0 0 1 1 0z"
/>
</svg>
</button>
<button
type="button"
@click="sortResult('UtenteNome', false)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 16a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2zm6.5-4.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 1 0z"
/>
</svg>
</button>
</div>
UtenteNome
</th>
<th>Options</th>
</tr>
</thead>
</table>
<table style="z-index: 1">
<thead>
<tr>
<th>Tessera</th>
<th>Nome</th>
<th>Cognome</th>
<th>Email</th>
<th>Telefono</th>
</tr>
</thead>
<tbody>
<!--<tr v-for="info in info" :key="index">-->
<tr v-for="utente in utenti" :key="title">
<td>{{ utente.tessera }}</td>
<td>{{ utente.nome }}</td>
<td>{{ utente.cognome }}</td>
<td>{{ utente.email }}</td>
<td>{{ utente.telefono }}</td>
</tr>
</tbody>
</table>
</div>
</template>
CodePudding user response:
You treat "filter" and "sort" as two different operations but those are two operations that need to be applied at the same time (so that sorting does not overwrite filtering result and vice versa). Also you are not using Vue reactivity at all. This is perfect use case for computed
This computed has 3 inputs:
- unfiltered and no sorted original array
- active filter
- active sort
<script>
import axios from 'axios'
export default {
name: 'Utenti',
data() {
return {
utenti: [],
modalTitle: '',
UtenteTessera: 0,
UtenteNome: '',
UtenteCognome: '',
UtenteEmail: '',
UtenteTelefono: '',
UtenteNomeFilter: '',
UtenteTesseraFilter: '',
// NEW
sort: {
prop: undefined,
asc: true
}
}
},
computed: {
utentiToDisplay() {
// filter first - this creates new array
const result = this.utenti.filter(el =>
el.UtenteTessera.toString()
.toLowerCase()
.includes(
this.UtenteTesseraFilter.toString().trim().toLowerCase()
)
&&
el.UtenteNome.toString()
.toLowerCase()
.includes(
this.UtenteNomeFilter.toString().trim().toLowerCase()
)
)
// now sort the results in-place if needed
if(this.sort.prop) {
result.sort((a, b) => {
if (this.sort.asc) {
return a[prop] > b[prop] ? 1 : a[prop] < b[prop] ? -1 : 0
} else {
return b[prop] > a[prop] ? 1 : b[prop] < a[prop] ? -1 : 0
}
})
}
return result
}
},
methods: {
refreshData() {
axios.post('https://localhost:7285/Utenti/GetDati').then((response) => { this.utenti = response.data.prova })
},
setSort(prop, asc) {
this.sort.prop = prop
this.sort.asc = asc
}
},
}
</script>
<div>
<table >
<thead>
<tr>
<th>
<div >
<input
v-model="UtenteTesseraFilter"
placeholder="Filter"
/>
<button
type="button"
@click="setSort('UtenteTessera', true)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5a.5.5 0 0 1 1 0z"
/>
</svg>
</button>
<button
type="button"
@click="setSort('UtenteTessera', false)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 16a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2zm6.5-4.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 1 0z"
/>
</svg>
</button>
</div>
Tessera
</th>
<th>
<div >
<input
v-model="UtenteNomeFilter"
placeholder="Filter"
/>
<button
type="button"
@click="setSort('UtenteNome', true)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5a.5.5 0 0 1 1 0z"
/>
</svg>
</button>
<button
type="button"
@click="setSort('UtenteNome', false)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 16a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2zm6.5-4.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 1 0z"
/>
</svg>
</button>
</div>
UtenteNome
</th>
<th>Options</th>
</tr>
</thead>
</table>
<table style="z-index: 1">
<thead>
<tr>
<th>Tessera</th>
<th>Nome</th>
<th>Cognome</th>
<th>Email</th>
<th>Telefono</th>
</tr>
</thead>
<tbody>
<!--<tr v-for="info in info" :key="index">-->
<tr v-for="utente in utentiToDisplay" :key="title">
<td>{{ utente.tessera }}</td>
<td>{{ utente.nome }}</td>
<td>{{ utente.cognome }}</td>
<td>{{ utente.email }}</td>
<td>{{ utente.telefono }}</td>
</tr>
</tbody>
</table>
</div>
</template>
CodePudding user response:
I've solved it.
<script>
import axios from "axios"
export default {
name: "Utenti",
data() {
return {
utenti: [],
modalTitle: "",
UtenteTessera: 0,
UtenteNome: "",
UtenteCognome: "",
UtenteEmail: "",
UtenteTelefono: "",
UtenteNomeFilter: "",
UtenteTesseraFilter: "",
sortKey: 'nome',
reverse:false
}
},
computed: {
utentiToDisplay() {
return this.utenti.filter(this.filterByName)
.filter(this.filterByTessera)
.sort(this.orderBy);
}
},
methods: {
filterByName: function (utente) {
if (this.UtenteNomeFilter.length === 0) {
return true;
}
return (utente.nome.toLowerCase().indexOf(this.UtenteNomeFilter.toLowerCase()) > -1);
},
filterByTessera: function (utente) {
if (this.UtenteTesseraFilter.length === 0) {
return true;
}
return (utente.tessera.toLowerCase().indexOf(this.UtenteTesseraFilter.toLowerCase()) > -1);
},
orderBy: function (utenteA, utenteB) {
let condition = (utenteA[this.sortKey] > utenteB[this.sortKey]);
if (this.reverse) {
return !condition;
}
else {
return condition;
}
}
}
And the template
<div>
<table >
<thead>
<tr>
<th>
<div >
<input
v-model="UtenteTesseraFilter"
placeholder="Filter"
/>
<button
type="button"
@click="setSort('UtenteTessera', true)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5a.5.5 0 0 1 1 0z"
/>
</svg>
</button>
<button
type="button"
@click="setSort('UtenteTessera', false)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 16a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2zm6.5-4.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 1 0z"
/>
</svg>
</button>
</div>
Tessera
</th>
<th>
<div >
<input
v-model="UtenteNomeFilter"
placeholder="Filter"
/>
<button
type="button"
@click="setSort('UtenteNome', true)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5a.5.5 0 0 1 1 0z"
/>
</svg>
</button>
<button
type="button"
@click="setSort('UtenteNome', false)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M2 16a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2zm6.5-4.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 1 0z"
/>
</svg>
</button>
</div>
UtenteNome
</th>
<th>Options</th>
</tr>
</thead>
</table>
<table style="z-index: 1">
<thead>
<tr>
<th>Tessera</th>
<th>Nome</th>
<th>Cognome</th>
<th>Email</th>
<th>Telefono</th>
</tr>
</thead>
<tbody>
<!--<tr v-for="info in info" :key="index">-->
<tr v-for="utente in utentiToDisplay" :key="title">
<td>{{ utente.tessera }}</td>
<td>{{ utente.nome }}</td>
<td>{{ utente.cognome }}</td>
<td>{{ utente.email }}</td>
<td>{{ utente.telefono }}</td>
</tr>
</tbody>
</table>
</div>
</template>