Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 filter/search list

Tags:

angular

I'm looking for the angular 2 way to do this.

I simply have a list of items, and I want to make an input whos job is to filter the list.

<md-input placeholder="Item name..." [(ngModel)]="name"></md-input>

<div *ngFor="let item of items">
{{item.name}}
</div>

What's the actual way of doing this in Angular 2? Does that requires a pipe?

like image 993
TheUnreal Avatar asked Nov 18 '16 13:11

TheUnreal


4 Answers

Search by multiple fields

Assuming Data:

items = [
  {
    id: 1,
    text: 'First item'
  },
  {
    id: 2,
    text: 'Second item'
  },
  {
    id: 3,
    text: 'Third item'
  }
];

Markup:

<input [(ngModel)]="query">
<div *ngFor="let item of items | search:'id,text':query">{{item.text}}</div>

Pipe:

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

@Pipe({
  name: 'search'
})
export class SearchPipe implements PipeTransform {
  public transform(value, keys: string, term: string) {

    if (!term) return value;
    return (value || []).filter(item => keys.split(',').some(key => item.hasOwnProperty(key) && new RegExp(term, 'gi').test(item[key])));

  }
}

One line for everything!

like image 75
Moshe Quantz Avatar answered Nov 19 '22 13:11

Moshe Quantz


You have to manually filter result based on change of input each time by keeping listener over input event. While doing manually filtering make sure you should maintain two copy of variable, one would be original collection copy & second would be filteredCollection copy. The advantage for going this way could save your couple of unnecessary filtering on change detection cycle. You may see a more code, but this would be more performance friendly.

Markup - HTML Template

<md-input #myInput placeholder="Item name..." [(ngModel)]="name" (input)="filterItem(myInput.value)"></md-input>

<div *ngFor="let item of filteredItems">
   {{item.name}}
</div>

Code

assignCopy(){
   this.filteredItems = Object.assign([], this.items);
}
filterItem(value){
   if(!value){
       this.assignCopy();
   } // when nothing has typed
   this.filteredItems = Object.assign([], this.items).filter(
      item => item.name.toLowerCase().indexOf(value.toLowerCase()) > -1
   )
}
this.assignCopy();//when you fetch collection from server.
like image 21
Pankaj Parkar Avatar answered Nov 19 '22 13:11

Pankaj Parkar


HTML

<input [(ngModel)] = "searchTerm" (ngModelChange) = "search()"/>
<div *ngFor = "let item of items">{{item.name}}</div>

Component

search(): void {
    let term = this.searchTerm;
    this.items = this.itemsCopy.filter(function(tag) {
        return tag.name.indexOf(term) >= 0;
    }); 
}

Note that this.itemsCopy is equal to this.items and should be set before doing the search.

like image 15
Akk3d1s Avatar answered Nov 19 '22 13:11

Akk3d1s


In angular 2 we don't have pre-defined filter and order by as it was with AngularJs, we need to create it for our requirements. It is time killing but we need to do it, (see No FilterPipe or OrderByPipe). In this article we are going to see how we can create filter called pipe in angular 2 and sorting feature called Order By. Let's use a simple dummy json data array for it. Here is the json we will use for our example

First we will see how to use the pipe (filter) by using the search feature:

Create a component with name category.component.ts

    import { Component, OnInit } from '@angular/core';
    @Component({
      selector: 'app-category',
      templateUrl: './category.component.html'
    })
    export class CategoryComponent implements OnInit {

      records: Array<any>;
      isDesc: boolean = false;
      column: string = 'CategoryName';
      constructor() { }

      ngOnInit() {
        this.records= [
          { CategoryID: 1,  CategoryName: "Beverages", Description: "Coffees, teas" },
          { CategoryID: 2,  CategoryName: "Condiments", Description: "Sweet and savory sauces" },
          { CategoryID: 3,  CategoryName: "Confections", Description: "Desserts and candies" },
          { CategoryID: 4,  CategoryName: "Cheeses",  Description: "Smetana, Quark and Cheddar Cheese" },
          { CategoryID: 5,  CategoryName: "Grains/Cereals", Description: "Breads, crackers, pasta, and cereal" },
          { CategoryID: 6,  CategoryName: "Beverages", Description: "Beers, and ales" },
          { CategoryID: 7,  CategoryName: "Condiments", Description: "Selishes, spreads, and seasonings" },
          { CategoryID: 8,  CategoryName: "Confections", Description: "Sweet breads" },
          { CategoryID: 9,  CategoryName: "Cheeses",  Description: "Cheese Burger" },
          { CategoryID: 10, CategoryName: "Grains/Cereals", Description: "Breads, crackers, pasta, and cereal" }
         ];
         // this.sort(this.column);
      }
    }
<div class="col-md-12">
  <table class="table table-responsive table-hover">
    <tr>
      <th >Category ID</th>
      <th>Category</th>
      <th>Description</th>
    </tr>
    <tr *ngFor="let item of records">
      <td>{{item.CategoryID}}</td>
      <td>{{item.CategoryName}}</td>
      <td>{{item.Description}}</td>
    </tr>
  </table>
</div>

2.Nothing special in this code just initialize our records variable with a list of categories, two other variables isDesc and column are declared which we will use for sorting latter. At the end added this.sort(this.column); latter we will use, once we will have this method.

Note templateUrl: './category.component.html', which we will create next to show the records in tabluar format.

For this create a HTML page called category.component.html, whith following code:

3.Here we use ngFor to repeat the records and show row by row, try to run it and we can see all records in a table.

Search - Filter Records

Say we want to search the table by category name, for this let's add one text box to type and search

<div class="form-group">
  <div class="col-md-6" >
    <input type="text" [(ngModel)]="searchText" 
           class="form-control" placeholder="Search By Category" />
  </div>
</div>

5.Now we need to create a pipe to search the result by category because filter is not available as it was in angularjs any more.

Create a file category.pipe.ts and add following code in it.

    import { Pipe, PipeTransform } from '@angular/core';
    @Pipe({ name: 'category' })
    export class CategoryPipe implements PipeTransform {
      transform(categories: any, searchText: any): any {
        if(searchText == null) return categories;

        return categories.filter(function(category){
          return category.CategoryName.toLowerCase().indexOf(searchText.toLowerCase()) > -1;
        })
      }
    }

6.Here in transform method we are accepting the list of categories and search text to search/filter record on the list. Import this file into our category.component.ts file, we want to use it here, as follows:

import { CategoryPipe } from './category.pipe';
@Component({      
  selector: 'app-category',
  templateUrl: './category.component.html',
  pipes: [CategoryPipe]   // This Line       
})

7.Our ngFor loop now need to have our Pipe to filter the records so change it to this.You can see the output in image below

enter image description here

like image 5
RAHUL KUMAR Avatar answered Nov 19 '22 12:11

RAHUL KUMAR