Home  >  Q&A  >  body text

Issues encountered when filtering arrays using search and dropdown menus in Vuejs

<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, user data will be fully loaded. Later based on two filters i.e. one for search filter I should filter out the array from all users array. Second, for the dropdown based on the status in the users array, I need to filter the array.

How to change the code to work properly. Currently, it does not filter arrays from searches or dropdowns. But it just displays the data.

P粉068510991P粉068510991204 days ago358

reply all(1)I'll reply

  • P粉593649715

    P粉5936497152024-03-29 18:02:15

    There are several changes required for this example to work properly.

    First, you need to update the displayed content. I recommend printing the variable sourceInfo instead of the list you have now, which will contain the filtered list. So in the HTML section add somewhere

    {{ sourceInfo }}

    After making this change, you should already receive an error message in the console because the contents of sourceInfo are now being used and therefore are ultimately evaluated. The content of the message is as follows:

    [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 containing the list of users:

    const res = this.users.filter((user) => ...

    Another error pops up:

    [Vue warn]: Error in render: "TypeError: user.name.toLowerCase().includes(...).sort is not a function"

    This comes from applying the sort() function on the boolean which is expected to be returned by the includes() function. So as a final step, remove the sort() part of the filter that checks if the user matches the text search criteria and applies it before returning the results:

    const res = this.users.filter((user) => {
      return user.name.toLowerCase().includes(this.search.toLowerCase());
    });
    
    ...
    
    return res.sort(compare);

    Basic functionality should now work. When checking the dropdown's filters, you may notice that for nok, an empty array is returned even if one user has the corresponding status. This is because the dropdown element nok has been assigned the value notok . So just change the value to nok.

    Here is the link to codesandbox that runs the code: https://codesandbox.io/s/vue-sort-problem-hgdm7?file=/src/components/HelloWorld.vue

    reply
    0
  • Cancelreply