Javascript How to filter through nested array data

Tags: , ,



I have a search field which filters through an array when I’m typing. So far it works ok, but I cannot search within the “courses” array! How can I achieve this? The complete array looks like this:

const data = [{
  name: "john doe",
  city: "blabla",
  zipcode: "1234",
  email: "test@test.com",
  phone: "12345678",
  courses: [
   {
     title: "some course",
     provider: "some provider",
     end_date: "some date"
    },
   {
     title: "another course",
     provider: "another provider",
     end_date: "another date"
    },
  ]
]

Here is my JS code so far, where I can search through all fields, except the “courses”-array:

data = data.filter(row => {
   return Object.keys(row).some(key => {
     return (
       String(row[key])
        .toLowerCase()
        .indexOf(filter) > -1
      );
   });
});

Can someone help me out?

Answer

The following will search both, all fields of your top level objects in dataas well as all fields in the objects of each course array:

const data = [{
  name: "john doe",
  city: "blabla",
  zipcode: "1234",
  email: "test@test.com",
  phone: "12345678",
  courses: [
   {
     title: "some course",
     provider: "some provider",
     end_date: "some date"
    },
   {
     title: "another course",
     provider: "another provider",
     end_date: "another date"
    },
  ]},
{
  name: "jane aire",
  city: "dooodaaah",
  zipcode: "987",
  email: "missjane@ladyjane.com",
  phone: "8997652",
  courses: [
   {
     title: "how to win",
     provider: "by herself",
     end_date: "tomorrow"
    },
   {
     title: "you can do it",
     provider: "Harry",
     end_date: "next week"
    },
  ]}
];

// check whether `filter` is found in `value`:
function chk(filter){return function(value){return String(value).toLowerCase().indexOf(filter)>-1}}
const res=document.getElementById('res');  // show found results in <pre id="res">

// whenever the input changes:
document.querySelector('input').oninput=ev=>{
 let chkfilt=chk(ev.target.value || null);
 res.innerHTML=JSON.stringify(
   data.filter(row => { return Object.values(row).some(chkfilt) 
                               || row.courses.some(o=>Object.values(o).some(chkfilt)) })
   ,null,2);
}
.as-console-wrapper {max-height:100% !important}
<input type="text" placeholder="search string ...">

<pre id="res"></pre>


Source: stackoverflow