I have found an excellent example for creating URL filters. I would like the results to be in a separate component though. In this example, all the code is in one file. Can someone help me to move the results to a separate component and also ensure the URL filters work when the different selections are made?
<template>
<div id="app">
<div id="app">
<h2>Items</h2>
<p>
<input type="search" placeholder="Filter by name" v-model="filter" />
<input
type="checkbox"
value="person"
id="personType"
v-model="typeFilter"
/>
<label for="personType">Only People</label>
<input type="checkbox" value="cat" id="catType" v-model="typeFilter" />
<label for="catType">Only Cats</label>
<input type="checkbox" value="dog" id="dogType" v-model="typeFilter" />
<label for="dogType">Only Dogs</label>
</p>
<ul>
<li v-for="item in items" :key="item">
{{ item.name }} ({{ item.type }})
</li>
</ul>
</div>
</div>
<!-- <Result v-for="item in items" :key="item" /> -->
</template>
<script>
//import Result from "@/components/Result.vue";
export default {
components: {
//Result,
},
data: function () {
return {
// allItems: ITEMS,
filter: "",
typeFilter: [],
ITEMS: [
{ name: "Ray", type: "person" },
{ name: "Lindy", type: "person" },
{ name: "Jacob", type: "person" },
{ name: "Lynn", type: "person" },
{ name: "Noah", type: "person" },
{ name: "Jane", type: "person" },
{ name: "Maisie", type: "person" },
{ name: "Carol", type: "person" },
{ name: "Ashton", type: "person" },
{ name: "Weston", type: "person" },
{ name: "Sammy", type: "cat" },
{ name: "Aleese", type: "cat" },
{ name: "Luna", type: "cat" },
{ name: "Pig", type: "cat" },
{ name: "Cayenne", type: "dog" },
],
};
},
created() {
let qp = new URLSearchParams(window.location.search);
let f = qp.get("filter");
if (f) this.filter = qp.get("filter");
let tf = qp.get("typeFilter");
if (tf) this.typeFilter = tf.split(",");
},
computed: {
items() {
this.updateURL();
return this.ITEMS.filter((a) => {
if (
this.filter !== "" &&
a.name.toLowerCase().indexOf(this.filter.toLowerCase()) === -1
)
return false;
if (this.typeFilter.length && !this.typeFilter.includes(a.type))
return false;
return true;
});
},
},
methods: {
updateURL() {
let qp = new URLSearchParams();
if (this.filter !== "") qp.set("filter", this.filter);
if (this.typeFilter.length) qp.set("typeFilter", this.typeFilter);
history.replaceState(null, null, "?" qp.toString());
},
},
};
</script>
CodePudding user response:
You need to read about props in component (vuejs.org/v2/guide/components-props.html).
I wrote you an example but not tested, hope it will be helpful.
<template>
<div id="app">
<h2>Items</h2>
<p>
<input type="search" placeholder="Filter by name" v-model="filter" />
<input
type="checkbox"
value="person"
id="personType"
v-model="typeFilter"
/>
<label for="personType">Only People</label>
<input type="checkbox" value="cat" id="catType" v-model="typeFilter" />
<label for="catType">Only Cats</label>
<input type="checkbox" value="dog" id="dogType" v-model="typeFilter" />
<label for="dogType">Only Dogs</label>
</p>
<ul>
<li v-for="item in items" :key="item">
{{ item.name }} ({{ item.type }})
</li>
</ul>
<Result v-bind:items="filteredItems" />
</div>
</template>
<script>
import Result from "@/components/Result.vue";
export default {
components: {
Result,
},
data: function () {
return {
filter: "",
typeFilter: [],
items: [
{ name: "Ray", type: "person" },
{ name: "Lindy", type: "person" },
{ name: "Jacob", type: "person" },
{ name: "Lynn", type: "person" },
{ name: "Noah", type: "person" },
{ name: "Jane", type: "person" },
{ name: "Maisie", type: "person" },
{ name: "Carol", type: "person" },
{ name: "Ashton", type: "person" },
{ name: "Weston", type: "person" },
{ name: "Sammy", type: "cat" },
{ name: "Aleese", type: "cat" },
{ name: "Luna", type: "cat" },
{ name: "Pig", type: "cat" },
{ name: "Cayenne", type: "dog" },
],
};
},
created() {
let qp = new URLSearchParams(window.location.search);
let f = qp.get("filter");
if (f) {
this.filter = qp.get("filter");
}
let tf = qp.get("typeFilter");
if (tf) {
this.typeFilter = tf.split(",");
}
},
computed: {
filteredItems() {
this.updateURL();
return this.items.filter((item) => item.name.toLowerCase().includes(this.filter.toLowerCase()));
},
},
methods: {
updateURL() {
let qp = new URLSearchParams();
if (this.filter !== "") {
qp.set("filter", this.filter);
}
if (this.typeFilter.length) {
qp.set("typeFilter", this.typeFilter);
}
history.replaceState(null, null, "?" qp.toString());
},
},
};
</script>
<template>
<div >
<ul>
<li v-for="item in items" :key="item">
{{ item.name }} ({{ item.type }})
</li>
</ul>
</div>
</template>
<script>
export default {
props: ['items'],
};
</script>