Tuesday, 30 April, 2019 UTC


Summary

When building Single Page Applications a feature I frequently find myself adding is a simple search filter. Nothing too in depth, I'll just want a text field to be able to quickly filter over items to find specific ones.
I'm going to share what I do, because it's quick to implement, performant enough, and often very helpful.
To start with, this technique assumes that the data you're filtering over is in the form of an array of objects. From there it's all standard libarary array and string methods.
Our Tools Array.prototype.filter
Array.prototype.filter is how we filter our array.
As a parameter, it takes a callback that it runs on each item of the array. This callback should return true or false for whether or not it should be a member of the filtered array.
let oneToTen = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let sixToTen = a.filter((element, index) =>  a > 5); // return [6, 7, 8, 9, 10];
String.prototype.toLowerCase
String.prototype.toLowerCase is nothing fancy. It takes a string, it turns all the letters to lowercase.
For this example it's purpose is string normalization. It's what's going to lets us find "The", even if we type in "the" or "tHe".
let lowercaseString = "Hello, World!".toLowerCase(); // returns "hello, world!"
In a more complete setup you may need to do much more for your string normalization.

String.prototype.includes
String.prototype.includes is the heavy lifter of the filter. You pass it a string and it gives you back true or false to let you know if its a substring of the original string.
let data = "I don't want to go, I don't want to go. Mr. Stark , please." // returns false.
let tony = data.includes("Mr. Stark"); //returns true
let peter = data.includes("Spiderman"); //return false
Pulling it all together
Laying out each of those, it should be pretty clear how it all comes together. What we want to do is as follows:
  1. Normalize search input.
  2. Normalize field we are searching on.
  3. Check if normalized search input is a substring(included) in the field we are searching on.
  4. Return a new array with only the items where the last statement was true.
So what does that looks like? Assuming the data looks like below:
let data = [
  {
    title: 'Ready Player One',
    author: 'Ernest Cline',
  },
  {
    title: 'The Circle',
    author: 'Dave Eggers',
  },
];
We can do a quick search filter over the authors by doing:
let substring = "est c";
let filteredData = data.filter(book => book.author.toLowerCase().includes(substring.toLowerCase()) 

/*
returns [
  {
    title: 'Ready Player One',
    author: 'Ernest Cline'
  }
]
Caveats
This method returns an array of all matchs, regardless of whether or not one is an exact match. If you want an exact match look instead to Array.prototype.find