I have an array of wines containing objects with data for each wine:
var wines = [ { _id: '59a740b8aa06e549918b1fda', wineryName: 'Some Winery', wineName: 'Pinot Noir', wineColor: 'Red', imageLink: '/img/FortBerensPN.png' }, { _id: '59a7410aaa06e549918b1fdb', wineryName: 'Some Winery', wineName: 'Pinot Gris', wineColor: 'White', imageLink: '/img/FortBerensPG.png' }, { _id: '59a74125aa06e549918b1fdc', wineryName: 'Some Winery', wineName: 'Rose', wineColor: 'Rose', imageLink: '/img/FortBerensRose.png' }, { _id: '59a74159aa06e549918b1fdd', wineryName: 'Some other Winery', wineName: 'Rose', wineColor: 'Rose', imageLink: '/img/FortBerensRose.png' }, { _id: '59a7417aaa06e549918b1fde', wineryName: 'Some other Winery', wineName: 'Pinot Gris', wineColor: 'White', imageLink: '/img/FortBerensPG.png' }, { _id: '59a8721f4fd43b676a1f5f0d', wineryName: 'Some other Winery', wineName: 'Pinot Gris', wineColor: 'White', imageLink: '/img/FortBerensPG.png' }, { _id: '59a872244fd43b676a1f5f0e', wineryName: 'Winery 3', wineName: 'Pinot Noir', wineColor: 'Red', imageLink: '/img/FortBerensPN.png' } ]
I can figure out how to search — case insensitive — for a wine object, while specifying which key of the object to search in, like this:
var search = 'Noir' filteredWines = function () { return wines.filter(function(wine){ return (wine.wineName.toLowerCase().indexOf(search.toLowerCase())>=0; }); };
Returns:
[ { _id: '59a740b8aa06e549918b1fda', wineryName: 'Some Winery', wineName: 'Pinot Noir', wineColor: 'Red', imageLink: '/img/FortBerensPN.png' }, { _id: '59a872244fd43b676a1f5f0e', wineryName: 'Winery 3', wineName: 'Pinot Noir', wineColor: 'Red', imageLink: '/img/FortBerensPN.png' } ]
However, if var search = 'Winery 3'
or var search = 'red'
then it will obviously return no results, as it’s looking in the value of wineName
of each object in the array.
So is there a way to use filter (or another method?) to search through all key values, or even better, multiple specified key values and return an array of the matching objects?
Something like:
filteredWines = function () { return wines.filter(function(wine){ return ((wine.wineName.toLowerCase() && wine.wineName.toLowerCase() && wine.wineName.toLowerCase()).indexOf(search.toLowerCase())>=0; }); };
Or am I completely barking up the wrong tree?
PS. I’m using Vue.js 2 so if there’s a better way inside vue then I’m all ears!
Advertisement
Answer
You could have a more generic function that will scan all the properties for the string. Loop through all property values with Object.values()
and use some
to bail out as soon as you have a match:
filteredWines = function (search) { var lowSearch = search.toLowerCase(); return wines.filter(wine => Object.values(wine).some(val => String(val).toLowerCase().includes(lowSearch) ) ); }
If you prefer to pass specific keys to search in:
filteredWines = function (search, keys) { var lowSearch = search.toLowerCase(); return wines.filter(wine => keys.some(key => String(wine[key]).toLowerCase().includes(lowSearch) ) ); }
Call as
filteredWines('Winery 3', ['wineryName', 'wineName']);