0
votes

I have a set of data which I need to filter via pipe. Now, in that data array, some objects have a nested array. Similar to this:

this.testArray = [
  {
    name: "Ford",
    cars: [
      {
        name: "Figo",
        year: "2015"
      },
      {
        name: "Ecosport",
        year: "2021"
      },
      {
        name: "Endeavour",
        year: "2021"
      }
    ],
    location: "USA"
  },
  {
    name: "Suzuki",
    location: "Japan"
  },
  {
    name: "Honda",
    cars: [
      {
        name: "Brio",
        year: "2015"
      },
      {
        name: "Amaze",
        year: "2021"
      },
      {
        name: "CR-V",
        year: "2021"
      }
    ],
    location: "Japan"
  },
  {
    name: "Hyundai",
    cars: [
      {
        name: "Tucson",
        year: "2015"
      },
      {
        name: "Creta",
        year: "2021"
      },
      {
        name: "Venuw",
        year: "2021"
      }
    ],
    location: "South Korea"
  },
  {
    name: "Renault",
    cars: [
      {
        name: "Duster",
        year: "2015"
      },
      {
        name: "Scala",
        year: "2021"
      },
      {
        name: "Kwid",
        year: "2021"
      }
    ],
    location: "France"
  }
];

Now, the requirement is that when I type a company name it should filter and when I type a car name, the same should happen with the nested array returning only the filtered car name. Eg: If I search for 'Figo', it should return me Ford and then Figo nested inside.

here is my pipe I am using for this:

@Pipe({ name: "carCompSearch" })
export class CarCompSearch implements PipeTransform {
  transform(carData: [], searchString: string) {
    if (!carData || !searchString) {
      return carData;
    }
    return carData.filter((item: any) => {
      return item.name.toLowerCase().includes(searchString.toLowerCase());
    });
  }
}

I know the pipe is incomplete. Need help in completing this.

and here is the template:

<div *ngFor="let comp of testArray | carCompSearch: searchString">
  <h2>{{comp.name}}</h2>
  <h5>{{comp.location}}</h5>
  <ul>
    <li *ngFor="let model of comp.cars">
      <span>{{model.name}} - {{model.year}}</span>
    </li>
  </ul>
</div>

your help is appreciated.

Here is the fork link:

https://codesandbox.io/s/custompipe-forked-5urrl

1

1 Answers

0
votes

This may help you out:

@Pipe({ name: "carCompSearch" })
export class CarCompSearch implements PipeTransform {
  transform(carData: any[], searchString: string) {
    if (!carData || !searchString) {
      return carData;
    }
    const carDataWithNestedFilter = carData.map((item) => {
      const newItem = { ...item }; // copy the item to not manipulate the original one
      newItem.cars = item.cars?.filter((car) =>
        car.name.toLowerCase().includes(searchString.toLowerCase())
      );
      return newItem;
    });
    return carDataWithNestedFilter.filter((item) => {
      const nameIncludes = item.name
        .toLowerCase()
        .includes(searchString.toLowerCase());
      return item.cars?.length > 0 || nameIncludes;
    });
  }
}