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:
- Init the state (data) on mounted hook (populate the "documents" variable inxpecting and traversing the DOM
- Create a computed value that will drive UI refresh (the "searchResults" variable)
- 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;
}
}
}
});