Answer the question
In order to leave comments, you need to log in
How to combine sorting and filtering?
I would like to understand how to do a search for a table to which a filter has already been applied. The list can be removed, because the search will still go through the table. I could not find such an answer on the Internet, or it is written in such a way that it will be understandable only to those who have been studying vue js for more than 1 week.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<style>
a:hover {
cursor: pointer;
}
/* ul{
display: none;
} */
</style>
<div id="app">
<p><input type="text" v-model="company" placeholder="Поиск..." /></p>
<ul>
<li v-for="phone in filteredList">
<p>{{ phone.title }} - {{ phone.company }}</p>
</li>
</ul>
<table>
<tr>
<td><a @click="sortParam='title'">Модель</a></td>
<td><a @click="sortParam='company'">Компания</a></td>
<td><a @click="sortParam='price'">Цена</a></td>
</tr>
<tr v-for="phone in sortedList">
<td>{{phone.title}}</td>
<td>{{phone.company}}</td>
<td>{{phone.price}}</td>
</tr>
</table>
</div>
<script src="https://unpkg.com/[email protected]"></script>
<script>
Vue.createApp({
data() {
return {
company: '',
sortParam: "",
phones: [
{ title: "iPhone 12", company: "Apple", price: 65000 },
{ title: "Galaxy S20", company: "Samsung", price: 63000 },
{ title: "Galaxy A10", company: "Samsung", price: 38000 },
{ title: "iPhone 10", company: "Apple", price: 45000 },
{ title: "Xiaomi Redmi 8", company: "Xiaomi", price: 42000 },
],
};
},
computed: {
sortedList() {
switch (this.sortParam) {
case "title":
return this.phones.sort(sortByTitle);
case "company":
return this.phones.sort(sortByCompany);
case "price":
return this.phones.sort(sortByPrice);
default:
return this.phones;
}
},
filteredList() {
let comp = this.company;
return this.phones.filter(function (elem) {
if (comp === '') return true;
else return elem.company.indexOf(comp) > -1;
})
},
},
}).mount("#app");
const sortByTitle = (d1, d2) =>
d1.title.toLowerCase() > d2.title.toLowerCase() ? 1 : -1;
const sortByCompany = (d1, d2) =>
d1.company.toLowerCase() > d2.company.toLowerCase() ? 1 : -1;
const sortByPrice = (d1, d2) => (d1.price > d2.price ? 1 : -1);
</script>
</body>
</html>
Answer the question
In order to leave comments, you need to log in
For fun.
Composition API [RU] + Script Setup [RU] .
Actually, demo: https://sfc.vuejs.org/#
Code:
<script setup>
import {ref, computed, watchEffect} from "vue";
const phones = ref([
{ title: "iPhone 12", company: "Apple", price: 65000 },
{ title: "Galaxy S20", company: "Samsung", price: 63000 },
{ title: "Galaxy A10", company: "Samsung", price: 38000 },
{ title: "iPhone 10", company: "Apple", price: 45000 },
{ title: "Xiaomi Redmi 8", company: "Xiaomi", price: 42000 },
]);
const companySearch = ref("");
const filteredList = computed(() => {
if (!companySearch.value) {
return phones.value;
}
const search = companySearch.value.trim().toLowerCase();
return phones.value.filter(elem => elem.company.toLowerCase().startsWith(search)); // .includes(search)
});
const sortParam = ref("");
const sortByTitle = (p1, p2) => p1.title.localeCompare(p2.title, undefined, {sensitivity: "base"});
const sortByCompany = (p1, p2) => p1.company.localeCompare(p2.company, undefined, {sensitivity: "base"});
const sortByPrice = (p1, p2) => p1.price - p2.price;
const sortedList = ref([]);
watchEffect(() => {
const array = filteredList.value; //const array = [...filteredList.value];
if (sortParam.value === "title") {
sortedList.value = array.sort(sortByTitle);
} else if (sortParam.value === "company") {
sortedList.value = array.sort(sortByCompany);
} else if (sortParam.value === "price") {
sortedList.value = array.sort(sortByPrice);
} else {
sortedList.value = array;
}
});
</script>
<script setup>
import {ref, computed} from "vue";
const phones = ref([
{ title: "iPhone 12", company: "Apple", price: 65000 },
{ title: "Galaxy S20", company: "Samsung", price: 63000 },
{ title: "Galaxy A10", company: "Samsung", price: 38000 },
{ title: "iPhone 10", company: "Apple", price: 45000 },
{ title: "Xiaomi Redmi 8", company: "Xiaomi", price: 42000 },
]);
const companySearch = ref("");
const filteredList = computed(() => {
if (!companySearch.value) {
return phones.value;
}
const search = companySearch.value.trim().toLowerCase();
return phones.value.filter(elem => elem.company.toLowerCase().startsWith(search)); // .includes(search)
});
/** @type {import("vue").Ref<("title"|"company"|"price")>} */
const orderBy = ref("title");
const orders = ref({ // if `true` — an order is reversed
title: false,
company: false,
price: false,
});
const isOrderReversed = computed(() => orders.value[orderBy.value]);
function toggleOrder() {
orders.value[orderBy.value] = !orders.value[orderBy.value];
}
/** @param {"title"|"company"|"price"} value */
function setOrderBy(value) {
if (orderBy.value === value) {
toggleOrder();
}
orderBy.value = value;
};
const {compare} = new Intl.Collator(undefined, {sensitivity: "base"});
function comparator(pre, cur) {
const k = isOrderReversed.value ? -1 : 1;
if (orderBy.value === "title") {
return compare(pre.title, cur.title) * k;
} else if (orderBy.value === "company") {
return compare(pre.company, cur.company) * k;
} else if (orderBy.value === "price") {
return (pre.price - cur.price) * k;
}
return 0;
}
const sortedList = computed(() => {
return filteredList.value.sort(comparator);
});
</script>
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question