0

I'm trying to filter a on a nested array inside an array of objects in an Angular app. Here's a snippet of the component code -

var teams = [
  { name: 'Team1', members: [{ name: 'm1' }, { name: 'm2' }, { name: 'm3' }] }, 
  { name: 'Team2', members: [{ name: 'm4' }, { name: 'm5' }, { name: 'm6' }] }, 
  { name: 'Team3', members: [{ name: 'm7' }, { name: 'm8' }, { name: 'm9' }] }
];

What I'm trying to achieve is if I search for m5 for example my result should be -

var teams = [
  { name: 'Team1', members: [] }, 
  { name: 'Team2', members: [{ name: 'm5' }] }, 
  { name: 'Team3', members: [] }
];

So I've got teams and filteredTeams properties and in my search function I'm doing -

onSearchChange(event: any): void {
  let value = event.target.value;
  this.filteredTeams = this.teams.map(t => {
    t.members = t.members.filter(d => d.name.toLowerCase().includes(value));
    return t;
  })
}

Now this does work to some extent however because I'm replacing the members it's destroying the array on each call (if that makes sense). I understand why this is happening but my question is what would be the best way to achieve this filter?

0

4 Answers 4

5

you were very close, the only thing that you did wrong was mutating the source objects in teams

basically you can use spread operator to generate a new entry and then return a whole new array with new values.

const teams = [
  { name: 'Team1', members: [{ name: 'm1' }, { name: 'm2' }, { name: 'm3' }] }, 
  { name: 'Team2', members: [{ name: 'm4' }, { name: 'm5' }, { name: 'm6' }] }, 
  { name: 'Team3', members: [{ name: 'm7' }, { name: 'm8' }, { name: 'm9' }] }
];

const value = 'm5';

const result = teams.map(t => {
  const members = t.members.filter(d => d.name.toLowerCase().includes(value));
  return { ...t, members };
})

console.log(result)

Sign up to request clarification or add additional context in comments.

Comments

0

Check this. Instead of hard coded m5 pass your value.

const teams = [
  { name: 'Team1', members: [{ name: 'm1' }, { name: 'm2' }, { name: 'm3' }] }, 
  { name: 'Team2', members: [{ name: 'm4' }, { name: 'm5' }, { name: 'm6' }] }, 
  { name: 'Team3', members: [{ name: 'm7' }, { name: 'm8' }, { name: 'm9' }] }
];

const filteredTeams = teams.map(team => ({ name: team.name, members: team.members.filter(member => member.name.includes('m5')) }));

console.log(filteredTeams);

Comments

0

You are mutating the original objects, but you could assing new properties to the result object for mapping instead.

var teams = [{ name: 'Team1', members: [{ name: 'm1' }, { name: 'm2' }, { name: 'm3' }] }, { name: 'Team2', members: [{ name: 'm4' }, { name: 'm5' }, { name: 'm6' }] }, { name: 'Team3', members: [{ name: 'm7' }, { name: 'm8' }, { name: 'm9' }] }],
    result = teams.map(o => Object.assign(
        {},
        o,
        { members: o.members.filter(({ name }) => name === 'm5') }
    ));
    
console.log(result);
console.log(teams);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

0

Try to seperate your filter function first:

const filterTeamMembers = (teams, filterArr) => {
    const useFilter = filterArr.map(x => x.toLowerCase());

    return teams.map(team => ({
        ...team,
        members: team.members.filter(member => useFilter.includes(member.name))
    }))
};
// =========== And then:

onSearchChange(event: any): void {
    let value = event.target.value;
    this.filteredTeams = filterTeamMembers(this.teams, [value]);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.