Issue
I have an array of "Invoices" object. and Within this array ,there is a nested array of "Items".
Example:
[
{
"invoiceNo":"10",
"customerId":"101",
"invoiceTotal":"2500",
"items":[
{
"itemId":"1",
"itemName":"TV"
},
{
"itemId":"2",
"itemName":"Laptop"
},
{
"itemId":"3",
"itemName":"PC"
}
]
},
{
"invoiceNo":"11",
"customerId":"102",
"invoiceTotal":"7500",
"items":[
{
"itemId":"2",
"itemName":"Laptop"
},
{
"itemId":"3",
"itemName":"PC"
}
]
}
]
I want to return only array of all invoices that contains "TV" item.
The following is my code
let text = queryText.toLowerCase();
return this.http
.get<Invoices[]>(
this.url + "/crm-operations/application/invoices",
{ headers: headerInfo }
)
.pipe(
map((invoicesData) =>
invoicesData.filter((invoice) => {
if (invoice.items) {
invoice.items.filter((row) => {
row.itemName.toLowerCase().indexOf(text)>-1;
});
}
})
)
);
The result is always an empty array
IT must return an array with the invoice number "10" object.
What is wrong is my code. and is there another way to solve this problem?
Solution
change the body of your map
operator to this:
invoicesData.filter((invoice) =>
// (1)
invoice.items?.some((row) => // (2)
// (3)
row.itemName.toLowerCase().indexOf(text)>-1
)
)
(1) removes curly braces to return the value (true
/false
) of invoice.items?.some(..)
(2) instead of filter
we use some
. It’s a bit more efficient since it doesn’t iterate over all remaining array items once the inner function returns true
for some item.
(3) removes curly braces to implicitly return the result of row.itemName.toLowerCase().indexOf(text)>-1