<template>
<div id="app">
<span v-if="isLoaded" class="select">
<select v-model="selectNum" name="text">
<option value="" selected="selected">status</option>
<option value="ok">ok</option>
<option value="notok">notok</option>
<option value="medium">medium</option>
</select>
</span>
<span class="search-wrapper">
<span class="bar">
<input
type="text"
v-model="search"
placeholder="filter"
class="s-bar"
/>
</span>
</span>
<div v-for="user in users" :key="user.id">
{{ user.name }}
<div v-for="list in lists" :key="list.id">
{{ list.pan }}
</div>
</div>
</div>
</template>
<script>
import { userdata } from "../assets/userdata";
import { listdata } from "../assets/listdata";
export default {
name: "HelloWorld",
data: function () {
return {
users: userdata,
lists: listdata,
search: "",
isLoaded: false,
selectNum: "",
};
},
created() {
this.isLoaded = true;
},
computed: {
sourceInfo() {
function compare(a, b) {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0;
}
const res = this.userList
.filter((user) => {
return user.name.toLowerCase().includes(this.search.toLowerCase());
})
.sort(compare);
if (this.selectNum) {
return res.filter((user) => user.status === this.selectNum);
}
return res;
},
},
};
</script>
Initially the user data will be loaded completely. Later based on two filters, i.e., One for search filter, I should filter the array out of all user array. second one, for drop down based on status in User array, I need to filter the array.
How do i make my code changes in order to work it correctly. at present it is not filtering the array either from search or from dropdown. But just displaying the data.
There are multiple changes required to make this example functioning.
First, you need to update what you are displaying. Instead of the list that you have now, I suggest to just print out the variable sourceInfo, which will contain the filtered list. Therefore, add somewhere to the HTML part
{{ sourceInfo }}
After this change, you should already get an error message in the console, because the content of sourceInfo is now in use and thus, finally evaluated. The message goes something around:
[Vue warn]: Error in render: "TypeError: this.userList is undefined"
So, you need to change this.userList to this.users which is an actual variable and contains the list of users:
const res = this.users.filter((user) => ...
And another error pops up:
[Vue warn]: Error in render: "TypeError: user.name.toLowerCase().includes(...).sort is not a function"
This one comes from applying the sort() function on a boolean, which is expected to be returned by the includes() function. Thus, as a last step, remove the sort() part of the filter which checks that the user matches the text search criteria, and apply it before returning the result:
const res = this.users.filter((user) => {
return user.name.toLowerCase().includes(this.search.toLowerCase());
});
...
return res.sort(compare);
The basic functionality should work by now. When checking your filters of the dropdown, you might notice that for nok an empty array is returned even though one user has the corresponding status. This comes from the fact, that the dropdown element nok has the value notok assigned. Therefore, by simply changing the value to nok you're good to go.
<option value="nok">nok</option>
Here is the link to a codesandbox of the running code: https://codesandbox.io/s/vue-sort-problem-hgdm7?file=/src/components/HelloWorld.vue