Reputation:
I have an array of objects with the following structure
arr = [ { name: "abc" , items: ["itemA","itemB","itemC"], days :138} ,
{ name: "def" , items: ["itemA1","itemB2","itemC1"], days :157} ,
{ name: "hfg" , items: ["itemAN","itemB7","itemC7"], days :189} ]
This array needs to be filtered based on the search input passed. I was able to achieve the same for the name
, where days is not getting filtered.
Also can someone help how to search across items
array too so it filters the rows based on input passed
This is what I have tried
handleSearch = (arr, searchInput) => {
let filteredData= arr.filter(value => {
return (
value.name.toLowerCase().includes(searchInput.toLowerCase()) ||
value.days.toString().includes(searchInput.toString())
);
});
console.log(filteredData);
//this.setState({ list: filteredData });
}
Upvotes: 2
Views: 15411
Reputation: 5544
You can use Array#some
and then perform the same kind of match that you've already done :
The some() method tests whether at least one element in the array passes the test implemented by the provided function. It returns a Boolean value.
handleSearch = (arr, searchInput) => {
const filteredData = arr.filter(value => {
const searchStr = searchInput.toLowerCase();
const nameMatches = value.name.toLowerCase().includes(searchStr);
const daysMatches = value.days.toString().includes(searchStr);
const oneItemMatches = value.items.some(item => item.toLowerCase().includes(searchStr));
return nameMatches || daysMatches || oneItemMatches;
});
console.log(filteredData);
//this.setState({ list: filteredData });
}
Upvotes: 3
Reputation: 5283
As your search value can apply to all fields in your data array, you can combine the values together in one array (row by row) and perform the search in one place.
To do that, I've provided a snippet below that will filter the original array checking each object's values after the transformations. These involve using Object.values()
to get the values of the object in an array, since this array is nested, we can make use of Array.flat()
to flatten it into just the strings and numbers, finally call Array.some()
to check if one of the values partially includes the search value (after they've both been lowercase-d).
const arr = [
{ name: "abc" , items: ["itemA","itemB","itemC"], days: 138 },
{ name: "def" , items: ["itemA1","itemB2","itemC1"], days: 157 },
{ name: "hfg" , items: ["itemAN","itemB7","itemC7"], days: 189 }
];
const handleSearch = (arr, searchInput) => (
arr.filter((obj) => (
Object.values(obj)
.flat()
.some((v) => (
`${v}`.toLowerCase().includes(`${searchInput}`.toLowerCase())
))
))
);
console.log('"A1" =>', JSON.stringify(handleSearch(arr, 'A1')));
console.log('189 =>', JSON.stringify(handleSearch(arr, 189)));
console.log('"nope" =>', JSON.stringify(handleSearch(arr, 'nope')));
NOTE: This approach has one obvious flaw, it will seach through numbers as strings, meaning that providing 89
as the search value will still return the second element.
Upvotes: 1