Filtro Angular 2 / lista de búsqueda


Estoy buscando la forma angular 2 de hacer esto.

Simplemente tengo una lista de elementos, y quiero hacer una entrada cuyo trabajo es filtrar la lista.

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

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

¿Cuál es la forma real de hacer esto en Angular 2? ¿Eso requiere una tubería?

 25
Author: TheUnreal, 2016-11-18

8 answers

Debe filtrar manualmente el resultado en función del cambio de entrada cada vez manteniendo el oyente sobre el evento input. Mientras realiza el filtrado manual, asegúrese de mantener dos copias de variable, una sería copia de la colección original y la segunda sería copia filteredCollection. La ventaja de ir de esta manera podría ahorrar su par de filtros innecesarios en el ciclo de detección de cambios. Es posible que vea más código, pero esto sería más amigable con el rendimiento.

Marcado-HTML Plantilla

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

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

Código

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.
 31
Author: Pankaj Parkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-27 08:17:49

Buscar por múltiples campos

Suponiendo Datos:

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

Marcado:

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

Tubo:

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])));

  }
}

Una línea para todo!

 56
Author: Moshe Quantz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-28 18:24:43

Datos

names = ['Prashobh','Abraham','Anil','Sam','Natasha','Marry','Zian','karan']

Puede lograr esto creando una tubería simple

<input type="text" [(ngModel)]="queryString" id="search" placeholder="Search to type">

Pipe

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

@Pipe({
    name: 'FilterPipe',
})
export class FilterPipe implements PipeTransform {
    transform(value: any, input: string) {
        if (input) {
            input = input.toLowerCase();
            return value.filter(function (el: any) {
                return el.toLowerCase().indexOf(input) > -1;
            })
        }
        return value;
    }
}

Esto filtrará el resultado basado en el término de búsqueda

Más información

 6
Author: Prashobh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-05 05:57:17

HTML

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

Componente

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

Tenga en cuenta que esto.itemsCopy es igual a esto.items and should be set before doing the search.

 4
Author: Akk3d1s,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-09 15:32:55

En angular 2 no tenemos filtro predefinido y orden por como lo fue con AngularJS, necesitamos crearlo para nuestros requisitos. Es hora de matar, pero tenemos que hacerlo, (ver No FilterPipe u OrderByPipe). En este artículo vamos a ver cómo podemos crear un filtro llamado pipe en angular 2 y una función de clasificación llamada Order By. Vamos a utilizar un simple matriz de datos json ficticio para ello. Aquí está el json que usaremos para nuestro ejemplo

Primero veremos cómo usar la tubería (filtro) usando la función de búsqueda:

Cree un componente con el nombre category.componente.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.Nada especial en este código solo inicializa nuestra variable records con una lista de categorías, se declaran otras dos variables isDesc y column que usaremos para ordenar estas últimas. Al final añadió esto.ordenar (esto.columna); esta última la usaremos, una vez tengamos este método.

Nota templateUrl:'./categoría.componente.html', que crearemos a continuación para mostrar los registros en formato tabluar.

Para esto crea una página HTML llamada categoría.componente.html, con el siguiente código:

3.Aquí usamos ngFor para repetir los registros y mostrar fila por fila, intentar ejecutarlo y podemos ver todos los registros en una tabla.

Registros de Filtro de búsqueda

Digamos que queremos buscar la tabla por nombre de categoría, para esto agreguemos un cuadro de texto para escribir y buscar

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

5.Ahora necesitamos crear una tubería para buscar el resultado por categoría porque el filtro ya no está disponible como lo estaba en angularjs.

Crea una categoría de archivo.tubo.ts y añadir el siguiente código en él.

    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.Aquí en transform method estamos aceptando la lista de categorías y el texto de búsqueda para buscar/filtrar el registro en la lista. Importa este archivo a nuestra categoría.componente.archivo ts, queremos usarlo aquí, de la siguiente manera:

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

7.Nuestro ngFor loop ahora necesita tener nuestra tubería para filtrar los registros así que cámbialo a esto.Puede ver la salida en la imagen de abajo

Introduzca aquí la descripción de la imagen

 4
Author: RAHUL KUMAR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-06 05:46:35

También puede crear un tubo de búsqueda para filtrar los resultados:

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

@Pipe({
  name : 'searchPipe',
})
export class SearchPipe implements PipeTransform {
  public transform(value, key: string, term: string) {
    return value.filter((item) => {
      if (item.hasOwnProperty(key)) {
        if (term) {
          let regExp = new RegExp('\\b' + term, 'gi');
          return regExp.test(item[key]);
        } else {
          return true;
        }
      } else {
        return false;
      }
    });
  }
}

Use pipe en HTML:

<md-input placeholder="Item name..." [(ngModel)]="search" ></md-input>
<div *ngFor="let item of items | searchPipe:'name':search ">
  {{item.name}}
</div>
 2
Author: ranakrunal9,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-22 03:02:35

Ligera modificación a la respuesta @Mosche, para el manejo si no existe ningún elemento de filtro.

TS :

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

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

        if (!term) {
            return value
        }
        let res = (value || []).filter((item) => keys.split(',').some(key => item.hasOwnProperty(key) && new RegExp(term, 'gi').test(item[key])));
        return res.length ? res : [-1];

    }
}

Ahora, en su HTML puede verificar a través del valor '-1', para no obtener resultados.

HTML :

<div *ngFor="let item of list | filterFromList: 'attribute': inputVariableModel">
            <mat-list-item *ngIf="item !== -1">
                <h4 mat-line class="inline-block">
                 {{item}}
                </h4>
            </mat-list-item>
            <mat-list-item *ngIf="item === -1">
                No Matches
            </mat-list-item>
        </div>
 0
Author: hamzox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-27 14:10:49

Pipes en Angular 2+ son una excelente manera de transformar y formatear datos directamente desde sus plantillas.

Las tuberías nos permiten cambiar datos dentro de una plantilla; es decir, filtrar, ordenar, formatear fechas, números, monedas, etc. Un ejemplo rápido es que puede transferir una cadena a minúsculas aplicando un filtro simple en el código de la plantilla.

Lista de Construido-en los Tubos de Lista de API Ejemplos

{{ user.name | uppercase }}

Ejemplo de Angular versión 4.4.7. ng version


Tubos Personalizados que acepta múltiples argumentos.

HTML « *ngFor="let student of students | jsonFilterBy:[searchText, 'name'] "
TS   « transform(json: any[], args: any[]) : any[] { ... }

Filtrar el contenido usando una tubería " json-filter-by.pipe.ts

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

@Pipe({ name: 'jsonFilterBy' })
@Injectable()
export class JsonFilterByPipe implements PipeTransform {

  transform(json: any[], args: any[]) : any[] {
    var searchText = args[0];
    var jsonKey = args[1];

    // json = undefined, args = (2) [undefined, "name"]
    if(searchText == null || searchText == 'undefined') return json;
    if(jsonKey    == null || jsonKey    == 'undefined') return json;

    // Copy all objects of original array into new Array.
    var returnObjects = json;
    json.forEach( function ( filterObjectEntery ) {

      if( filterObjectEntery.hasOwnProperty( jsonKey ) ) {
        console.log('Search key is available in JSON object.');

        if ( typeof filterObjectEntery[jsonKey] != "undefined" && 
        filterObjectEntery[jsonKey].toLowerCase().indexOf(searchText.toLowerCase()) > -1 ) {
            // object value contains the user provided text.
        } else {
            // object didn't match a filter value so remove it from array via filter
            returnObjects = returnObjects.filter(obj => obj !== filterObjectEntery);
        }
      } else {
        console.log('Search key is not available in JSON object.');
      }

    })
    return returnObjects;
  }
}

Añadir a @NgModule " Añadir JsonFilterByPipe a su lista de declaraciones en su módulo; si se olvida de hacer esto, obtendrá un error para jsonFilterBy. Si se agrega al módulo, entonces está disponible para todos los componentes de ese módulo.

@NgModule({
  imports: [
    CommonModule,
    RouterModule,
    FormsModule, ReactiveFormsModule,
  ],
  providers: [ StudentDetailsService ],
  declarations: [
    UsersComponent, UserComponent,

    JsonFilterByPipe,
  ],
  exports : [UsersComponent, UserComponent]
})
export class UsersModule {
    // ...
}

Nombre del archivo: users.component.ts y StudentDetailsService se crea a partir de este enlace.

import { MyStudents } from './../../services/student/my-students';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { StudentDetailsService } from '../../services/student/student-details.service';

@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: [ './users.component.css' ],

  providers:[StudentDetailsService]
})
export class UsersComponent implements OnInit, OnDestroy  {

  students: MyStudents[];
  selectedStudent: MyStudents;

  constructor(private studentService: StudentDetailsService) { }

  ngOnInit(): void {
    this.loadAllUsers();
  }
  ngOnDestroy(): void {
    // ONDestroy to prevent memory leaks
  }

  loadAllUsers(): void {
    this.studentService.getStudentsList().then(students => this.students = students);
  }

  onSelect(student: MyStudents): void {
    this.selectedStudent = student;
  }

}

Nombre del archivo: users.component.html

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

    <h2>Present are Students</h2>
    <ul class="students">
    <li *ngFor="let student of students | jsonFilterBy:[searchText, 'name'] " >
        <a *ngIf="student" routerLink="/users/update/{{student.id}}">
            <span class="badge">{{student.id}}</span> {{student.name | uppercase}}
        </a>
    </li>
    </ul>
</div>
 0
Author: Yash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-25 07:37:20