Simple yet powerful search mixins for vuejs

profile picture

Simple yet powerful search mixins for vuejs

If you ever worked on a vuejs project, you surely one time build a list of data. And when you have this nice listing, you probably want to add a little search input on top. So that your users can type something and filter through the results.

The quick and easy way to do that is simply doing something like this:

<template>
  <div>
    <input type="search" v-model="search" />
    <ul>
      <li v-for="item in filteredItems" :key="item">
        {{ item }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: ["banana", "carrot"],
      search: "",
    };
  },

  computed: {
    filteredItems() {
      return this.items.filter((i) => i.includes(this.search));
    },
  },
};
</script>

Now if we complicate things a little bit and use an array of objects, users for exemple, things might get a little bit more trickier. In the following example we will search through the firstName and the lastName of each user:

<template>
  <div>
    <input type="search" v-model="search" />
    <ul>
      <li v-for="item in filteredItems" :key="item.id">
        {{ item.firstName }}
        {{ item.lastName }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, firstName: "Clement", lastName: "Rigo" },
        { id: 2, firstName: "Bernard", lastName: "Werber" },
      ],
      search: "",
    };
  },

  computed: {
    filteredItems() {
      return this.items.filter((i) => {
        return (
          i.firstName.includes(this.search) || i.lastName.includes(this.search)
        );
      });
    },
  },
};
</script>

You maybe see already where I'm coming with this πŸ˜„

If we have an array of very large objects with tons of attribute that are all searchable, your script will get heavier and heavier.

This is why I made this simple mixins:

// /mixins/search.js
export default {
    methods: {
        searchHasResult (searchable, query) {
            const terms = query ? query.split(' ') : []
            const matches = []
            let stop = false

            terms.forEach((term) => {
                const termResults = []
                searchable.forEach((word) => {
                    if (word) {
                        const result = word
                            .toLowerCase()
                            .includes(term ? term.toLowerCase() : '')
                        if (result) { termResults.push(result) }
                        matches.push(result)
                    }
                })

                if (termResults.length === 0) {
                    stop = true
                }
            })
            if (stop) {
                return false
            }
            return matches.filter(m => m).length >= terms.length
        }
    }
}

Then in your vue components, update the filteredItems computed method with :

filteredItems() {
  return this.items.filter((item) => {
    const searchable = [item.firstName, item.lastName]; // list all searchable strings here
    return this.searchHasResult(searchable, this.searchTerm);
  });
}
vuejs
search
filtering

about me

profile picture

I consider myself as an IT Business Artisan. Or Consultant CTO. I'm a self-taught Web Developper, coach and teacher. My main work is helping and guiding digital startups.

more about me

follow me

newsletter

A weekly email with the latests articles

support my work

Start trading on binance
  • BTC

    BTC

    18SY81ejLGFuJ9KMWQu5zPrDGuR5rDiauM

  • ETH

    ETH

    0x519e0eaa9bc83018bb306880548b79fc0794cd08

  • Monero

    XMR

    895bSneY4eoZjsr2hN2CAALkUrMExHEV5Pbg8TJb6ejnMLN7js1gLAXQySqbSbfzjWHQpQhQpvFtojbkdZQZmM9qCFz7BXU

2024 © My Dynamic Production SRL All rights Reserved.