0

I want to create a custom search filter in Angular 4. Names should contain search text and the corresponding name and image should be displayed. I have tried in the code below, but it doesn't work. I can't find the reason.

JSON data:

[  
   {  
      "name":"The Birds",
      "poster-image":"poster5.jpg"
   },
   {  
      "name":"Rear Window",
      "poster-image":"poster8.jpg"
   },
   {  
      "name":"Family Pot",
      "poster-image":"poster5.jpg"
   },
   {  
      "name":"Family Pot",
      "poster-image":"poster9.jpg"
   }
]

HTML code:

<div id="ProductContainer">
    <input [(ngModel)]="searchText" placeholder="search text goes here">
  <div id="Product"  *ngFor = "let data of httpdatanew">
    <img src="\assets\images\{{data.posterimage}}">
    <br/>
    <p id="Prodname">{{data.name | prodfilter : searchText}}</p>
  </div>
</div>

Filter.TS:

import { Pipe,PipeTransform} from '@angular/core';
@Pipe ({
  name : 'prodfilter'
})

export class FilterPipe implements PipeTransform {
    transform(value: any, input: string) {
        if (input) {
            input = input.toLowerCase();
            return value.filter(function (el: any) {
                return el.toLowerCase().includes(input);
            })
        }
        return value;
    }
}
2
  • You need to have the pipe on ngfor like this. <div id="Product" *ngFor = "let data of httpdatanew | prodfilter : searchText"> Commented Jun 5, 2018 at 19:05
  • can you provide more component.ts code Commented Jun 5, 2018 at 19:19

2 Answers 2

1

The following will help you to achieve the same:

HTML

<div id="ProductContainer">
  <input [(ngModel)]="searchText" placeholder="search text goes here" (ngModelChange)="prodFilter()">
  <div id="Product" *ngFor="let data of httpdatanew">
    <img src="\assets\images\{{data.posterimage}}">
    <br/>
    <p id="Prodname">{{data.name}}</p>
  </div>
</div>

FiltradoService

import { Injectable, PipeTransform } from '@angular/core';

@Injectable()
export class FiltradoService implements PipeTransform {

  constructor() { }

  transform(lista: any[], filter: any): any[] {
    if (!lista || !filter) {
      return lista;
    }
    return lista.filter((item: any) => this.applyFilter(item, filter));
  }

  applyFilter(arreglo: any, filter: any): boolean {
    for (const field in filter) {
      if (filter[field]) {
        if (typeof filter[field] === 'string') {
          if (arreglo[field].toLowerCase().indexOf(filter[field].toLowerCase()) === -1) {
            return false;
          }
        } else if (typeof filter[field] === 'number') {
          if (arreglo[field] !== filter[field]) {
            return false;
          }
        }
      }
    }
    return true;
  }
}

Filter.TS

Include FiltradoService in your TS file

import { FiltradoService } from '../../../service/filtrado.service';

and put the below code in the TS file

export class AppComponent implements OnInit {

httpdatanew = [
    {
      "name": "The Birds",
      "poster-image": "poster5.jpg"
    },
    {
      "name": "Rear Window",
      "poster-image": "poster8.jpg"
    },
    {
      "name": "Family Pot",
      "poster-image": "poster5.jpg"
    },
    {
      "name": "Family Pot",
      "poster-image": "poster9.jpg"
    }
  ]
searchText: any;
httpDataOrig: any;

 constructor( private filtradoService: FiltradoService){}

 ngOnInit() {

    this.httpDataOrig = this.httpdatanew;
}

prodFilter() {

    this.httpdatanew = this.filtradoService.transform(this.httpDataOrig, { 'name': this.searchText })


  }

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

Comments

0

If i am not wrong this is what you are trying to achieve.
Whenever i type in the text box and if it matches the name of any data in the list then i need to show the image and corresponding name, correct?

You can achieve using *ngIf in the template without the need for a pipe as shown below. This will not load the elements in DOM until your condition is satisfied.

<div id="ProductContainer">
 <input [(ngModel)]="searchText" placeholder="search text goes here">
  <div id="Product"  *ngFor = "let data of httpdatanew">
   <div *ngIf="data.name.toLowerCase().includes(searchText.toLowerCase()) 
        && searchText.length != 0">

     <img src="\assets\images\{{data.posterimage}}">
     <br/>
     <p id="Prodname">{{data.name}}</p>

   </div>
  </div>
</div>

You can remove && searchText.length != 0 from *ngIf if you want to show all the data by default when the text box is empty.

3 Comments

Thank you for the answer. It works but not for the first time...My requirement is first time all the products should display and then if we enter search text it should filter accordingly. With above code first time nothing appears. After giving search text its filtering accordingly and displaying. and if we remove search text also it loads everything correctly. Only problem is initially its not loading everything.Can you please suggest any ideas?
That is because value of searchText is not defined. set the value of searchText as searchText: string = ''; in ts file. Now working fine :)
Yeah u can set it as searchText: string=' ' in ngOnInit. Good to know that it's working.

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.