I want to implement a keyword search for a field which is located inside Nested Array of Objects. How can I achieve it?
Data -
const groupList = [{
"group_name": "General",
"trainings": [
{
"id": 1,
"training_name": "Plural Sight",
},
{
"id": 2,
"training_name": "Google Maps",
}
]
}]
Code -
const [groupsData, setGroupsData] = useState([]);
const lowerContains = (str1, str2) => str1 && str2 && str1.toLowerCase().indexOf(str2.toLowerCase()) !== -1;
const handleSearch = searchKeyword => {
if (searchKeyword && searchKeyword.trim()) {
const groupFiltered = groupList.filter(item => item.group_name && lowerContains(item.group_name, searchKeyword));
setGroupsData( groupFiltered );
return;
}
setGroupsData({ [...groupList] });
};
Currently I am able to search with group_name
but I want to also search with training_name
inside trainings
.
CodePudding user response:
Assuming you want to keep the group object if the searchKeyword
is contained within the group name OR one of the training name objects, you can use .some()
. By using .some()
on trainings
, you can check if there is at least one object within the trainings
array that contains a training_name
value that matches your keyword search:
const groupFiltered = groupList.filter(item =>
(item.group_name && lowerContains(item.group_name, searchKeyword)) ||
(item.trainings.some(training => lowerContains(training.training_name, searchKeyword)))
);
Note: In the example data you shared, group_name
always contains a value, so you can remove the item.group_name &&
check if that is always the case.
See working example below:
const groupList = [{ "group_name": "General", "trainings": [{ "id": 1, "training_name": "Plural Sight", }, { "id": 2, "training_name": "Google Maps", } ] }];
const lowerContains = (x, y) => x.toLowerCase().includes(y.toLowerCase());
const searchKeyword = "Plural";
const groupFiltered = groupList.filter(item =>
(item.group_name && lowerContains(item.group_name, searchKeyword)) ||
(item.trainings.some(training => lowerContains(training.training_name, searchKeyword)))
);
console.log(groupFiltered);
CodePudding user response:
You can search inside the trainings
if group_name
is not matched using Array.prototype.some() operation on the trainings
.
Try like below.
const handleSearch = (searchKeyword) => {
if (searchKeyword && searchKeyword.trim()) {
const groupFiltered = groupList.filter(
(item) =>
(item.group_name && lowerContains(item.group_name, searchKeyword)) ||
item.trainings.some(({ training_name }) =>
lowerContains(training_name, searchKeyword)
)
);
setGroupsData(groupFiltered);
return;
}
setGroupsData(groupList);
};
CodePudding user response:
You can use javascript's "Array.some" method.
const containsTraining = (item, keyword) => {
return item.some(
(training) =>
training.training_name && lowerContains(training.training_name, keyword)
);
};
This will return true if item (one single group) contains at least one training that has the training name search keyword.