Reputation: 2912
I'm trying to filter a large array of objects that also have nested values.
I need to match shortName OR description OR isoCode. Some of the items may have 20+ countries but most have 1 to 5.
{
countries: Array(1)
0:
description: "United Kingdom"
isoCode: "GB"
1:
description: "Italy"
isoCode: "IT"
shortName: "AIB (NI)"
},
// * 2000
I've tried building on this with limited success.
methods: {
filterInstitutions: function (items: any, event: any): void {
console.log(items, event.target.value);
if (event === '') {
newFunction(items);
} else {
this.listedInstitutions = items.filter((item: any) => {
return item.shortName.toLowerCase().includes(event.target.value.toLowerCase());
})
}
},
},
I am building this in Vue (typescript) but understand its as much of a JS question than a Vue one.
Any suggestions welcome.
Upvotes: 0
Views: 69
Reputation: 16309
Using filter()
and some()
:
function filterInstitutions (items, {target: {value}}) {
const isMatch = text => text.toLowerCase().includes(value.toLowerCase());
return items.filter(({shortName, countries}) => (
isMatch(shortName) || countries.some(({description, isoCode}) => (
isMatch(description) || isMatch(isoCode)
))
));
};
Upvotes: 1
Reputation: 50787
You could create an array of properties to search on within your object(s) and determine if any matches exist.
this.listedInstitutions = items.filter((item: any) => {
return item.countries.filter(
country => ['description', 'isoCode', 'shortName'].filter(prop => item.prop && item.prop.toLowerCase().includes(event.target.value.toLowerCase()).length > 0
).length > 0
})
Upvotes: 1
Reputation: 42736
You will need to add in tests for the description
and isoCode
of your countries
property to your filter function.
One way would be to use the Array's some()
method which will test if any of the array element's match any test you setup in the callback. It will then return true
if any do match and false
if not.
let testValue = event.target.value.toLowerCase();
this.listedInstitutions = items.filter((item: any) => {
//test the shortName
let matchesShortName = item.shortName.toLowerCase().includes(testValue);
//loop through countries and see if any description or isoCode match
let matchesDescIsoCode = item.countries.some((item:any) => {
let desc = item.description.toLowerCase();
let code = item.isoCode.toLowerCase();
return desc.includes(testValue) || code.includes(testValue);
});
return matchesShortName || matchesDescIsoCode;
})
Example
function doFilter(event, items) {
let testValue = event.target.value.toLowerCase();
let listedInstitutions = items.filter((item) => {
let matchesShortName = item.shortName.toLowerCase().includes(testValue);
let matchesDescIsoCode = item.countries.some((item) => {
let desc = item.description.toLowerCase();
let code = item.isoCode.toLowerCase();
return desc.includes(testValue) || code.includes(testValue);
});
return matchesShortName || matchesDescIsoCode;
});
console.clear();
console.log("Filtered List");
console.log(listedInstitutions);
}
let someItems = [{
countries: [{
description: "United Kingdom",
isoCode: "GB"
},
{
description: "Italy",
isoCode: "IT"
}
],
shortName: "AIB (NI)"
}, {
countries: [{
description: "United States",
isoCode: "US"
},
{
description: "Italy",
isoCode: "IT"
}
],
shortName: "ABC (DE)"
}]
<input type="text" oninput="doFilter(event,someItems)">
Upvotes: 2