Skip to page content

Search in page with Vue.js

Vue.js is an outstanding library we can use to build complex frontend UI and/or apps, but it can also be used to implement small features even if we’re working with a legacy/old project.

Imaging a page (eg. built from a CMS) with a list of documents and we want to give the user the power of a search feature.

In Vue.js we should think, first of all, about data, so:

  1. Init the state (data) on mounted hook (populate the “documents” variable inxpecting and traversing the DOM
  2. Create a computed value that will drive UI refresh (the “searchResults” variable)
  3. Add a couple of methods to improve the accessibility (handleClickOnBody and handleKeyUp)

This is the final JavaScript code:

var searchApp = new Vue({
  el: "#searchapp",

  data: {
    documents: [],
    searchString: "",
    searchResultsVisible: true,
  },

  mounted: function () {
    docsEls = document.querySelectorAll(".list__item");
    for (const item of Array.from(docsEls)) {
      this.documents.push({
        text: item.querySelector(".list__item__description").innerHTML,
      });
    }

    document.documentElement.addEventListener("click", this.handleClickOnBody);

    document.addEventListener("keyup", this.handleKeyUp);
  },

  computed: {
    activeSearchString: function () {
      return this.searchString.length >= 3 ? this.searchString : "";
    },

    searchResults: function () {
      if (this.activeSearchString !== "") {
        return this.documents.filter(
          (d) =>
            d.text
              .toLowerCase()
              .includes(this.activeSearchString.toLowerCase()) == true
        );
      } else {
        return [];
      }
    },
  },

  methods: {
    handleClickOnBody: function (e) {
      const target = e.target;
      const searchEl = this.$refs.searchEl;

      if (target !== searchEl && !searchEl.contains(target)) {
        this.searchResultsVisible = false;
      } else {
        this.searchResultsVisible = true;
      }
    },

    handleKeyUp: function (e) {
      if (e.key === "Escape") {
        this.searchResultsVisible = false;
      }
    },
  },
});

Here you can find a complete CodePen