Mam tablicę obiektów o nazwie allLeads. Każdy obiekt ma inną tablicę obiektów zwanych leadami. Teraz mam pojedynczy pasek wyszukiwania, w którym użytkownik może wpisać cokolwiek i mam funkcję o nazwie onChange, która sprawdzi wartość wyszukiwania w czterech różnych pozycjach w tablicy - leadName, która jest na najwyższym poziomie we wszystkich obiektach i currentCompany, leadActivity i status, które znajdują się wewnątrz obiektów w tablicy leadów. W tablicy leadów, jeśli użytkownik wpisze link w pasku wyszukiwania, to tylko obiekt z currentCompany jako linkedin zostanie zwrócony, a nie ten z google. Muszę jakoś znaleźć sposób na zwrócenie obiektów tablicy na podstawie tych czterech parametrów, ale wszystko, co próbowałem do tej pory, zawiodło. Proszę o wybaczenie, jeśli pytanie zostanie powtórzone, ponieważ do tej pory nie znalazłem podobnego zapytania.

//Array to search

const allLeads = [
{
leadName: 'react',
leads: [
  {
    currentCompany: 'linkedin',
    leadActivity: 'messaged',
    status: 'connected'
  },
  {
    currentCompany: 'google',
    leadActivity: 'messaged',
    status: 'not connected'
  }
],
leadId: '555',
userId: '555'
},
{
leadName: 'angular',
leads: [
  {
    currentCompany: 'walmart',
    leadActivity: 'messaged',
    status: 'connected'
  },
  {
    currentCompany: 'amazon',
    leadActivity: 'not messaged',
    status: 'not connected'
  },
],
leadId: '666',
userId: '666'
}
]

Do tej pory próbowałem to, ale nie działa z filtrem wewnątrz filtra. Nie działa też z filtrem wewnątrz mapy.

export const searchLeads = (allLeads, value) => {
 const newLeads = allLeads.filter(({ leadName, leads }) => {
  leads.filter(({ currentCompany, leadActivity, status }) => {
    return (
      filterItem(leadName, value)
      ||
      filterItem(currentCompany, value)
      ||
      filterItem(leadActivity, value)
      ||
      filterItem(status, value)
    );
  })
  return newLeads;
}
 )};

const filterItem = (item, itemToCheck) => {
if(item.toLowerCase().includes(itemToCheck.toLowerCase())) return true;
else return false;
}
0
user9667412 3 kwiecień 2020, 21:33

3 odpowiedzi

Najlepsza odpowiedź

Oto fragment tego, czego potrzebujesz, wraz z komentarzami https://jsbin.com/zeyomidafa/edit?js,console

const allLeads = [
  {
    leadName: 'react',
    leads: [
    {
      currentCompany: 'linkedin',
      leadActivity: 'messaged',
      status: 'connected'
    },
    {
      currentCompany: 'google',
      leadActivity: 'messaged',
      status: 'not connected'
    }
    ],
    leadId: '555',
    userId: '555'
  },
  {
    leadName: 'angular',
    leads: [
      {
        currentCompany: 'walmart',
        leadActivity: 'messaged',
        status: 'connected'
      },
      {
        currentCompany: 'amazon',
        leadActivity: 'not messaged',
        status: 'not connected'
      },
    ],
    leadId: '666',
    userId: '666'
  }
]


function filter(aleads, q){
  // map the list and only keep leads matching the query
  let aleadsDeepFilter = aleads.map(
     function(oneLead){
       return {
         ...oneLead,
         leads: oneLead.leads.filter(
           function(_lead){
             return (_lead.status === q) || (_lead.leadActivity === q) || (_lead.currentCompany === q)
           }
         )
       }
     }
  );

  // second filter, return items that have leads left from previous filter + matching the leadName
  aleadsDeepFilter = aleadsDeepFilter.filter(
    function(oneLead){
      return (oneLead.leadName === q) || (oneLead.leads.length > 0)
    }
  )

  return aleadsDeepFilter;

}


console.log(filter(allLeads, "angular"))
console.log(filter(allLeads, "google"))


0
naoufal bardouni 3 kwiecień 2020, 18:54

Czy mógłbyś zrestrukturyzować swój obiekt? Myślę, że twoja złożoność wynika z faktu, że organizujesz swoje obiekty w bardzo złożony (zagnieżdżony) sposób.

Byłbym prosty jak:

simplerArrayOfObj =
[{ leadname:'whatever', currentCompany:'whatever', leadActivity:'', status:'whatever'},
{ leadname:'whatever', currentCompany:'whatever', leadActivity:'', status:'whatever'}]

Stąd pytanie:

   const newArrayFiltered = function search(leadname, currentCompany, leadActivity, status){
    //validate the fields first
    // ...more code
     return simplerArrayOfObj.filter(arr=> arr.leadname === leadname || arr.currentCompany === currentCompany || arr.leadActivity === leadActivity || arr.status === status)
    }

Dzięki tej nowej tablicy newArrayFiltered możesz robić wszystkie głębokie poziomy rzeczy, które chcesz.

0
iwaduarte 3 kwiecień 2020, 18:45

Array.prototype.filter zawsze zwróci tablicę. W allLeads.filter nigdy niczego nie zwracasz, więc nigdy nie wiadomo, czy określony element spełnia te kryteria.

Aby sprawdzić, które produkty spełniają Twoje kryteria, proponuję zmienić leads.filter(({ currentCompany, leadActivity, status }) => { na return leads.filter(({ currentCompany, leadActivity, status }) => {

Zmień także allLeads.filter(({ leadName, leads }) => { na mapę z allLeads.map(({ leadName, leads }) => {

To da ci tablicę tablic. Jeśli chcesz to spłaszczyć, możesz użyć lodash lub czegoś takiego:

const flattenedArray = arrayOfArrays.reduce((acc, arr) => {
  return acc.concat(arr);
}, []);
0
sdotson 3 kwiecień 2020, 18:47