¿Cómo filtro una matriz con TypeScript en Angular 2?

109

La herencia de datos de padres e hijos de ng-2 ha sido una dificultad para mí.

Lo que parece que podría ser una buena solución práctica de trabajo es filtrar mi matriz total de datos a una matriz que consta de solo datos secundarios a los que hace referencia una única identificación de padre. En otras palabras: la herencia de datos se convierte en filtrado de datos por una identificación principal.

En un ejemplo concreto, esto puede verse así: filtrar una matriz de libros para mostrar solo los libros con un determinado store_id.

import {Component, Input} from 'angular2/core';

export class Store {
  id: number;
  name: string;
}

export class Book {
  id: number;
  shop_id: number;
  title: string;
}

@Component({
  selector: 'book',
  template:`
    <p>These books should have a label of the shop: {{shop.id}}:</p>

    <p *ngFor="#book of booksByShopID">{{book.title}}</p>
  `
])
export class BookComponent {
  @Input()
  store: Store;

  public books = BOOKS;

  // "Error: books is not defined"
  // ( also doesn't work when books.filter is called like: this.books.filter
  // "Error: Cannot read property 'filter' of undefined" )
  var booksByStoreID = books.filter(book => book.store_id === this.store.id)
}

var BOOKS: Book[] = [
  { 'id': 1, 'store_id': 1, 'name': 'Dichtertje' },
  { 'id': 2, 'store_id': 1, 'name': 'De uitvreter' },
  { 'id': 3, 'store_id': 2, 'name': 'Titaantjes' }
];

TypeScript es nuevo para mí, pero creo que estoy cerca de hacer que las cosas funcionen aquí.

(También puede ser una opción sobrescribir la matriz de libros original y luego usarla *ngFor="#book of books").

EDITAR Acercándonos, pero aún dando un error.

//changes on top:
import {Component, Input, OnInit} from 'angular2/core';

// ..omitted

//changed component:
export class BookComponent implements OnInit {
  @Input() 
  store: Store;

  public books = BOOKS;

  // adding the data in a constructor needed for ngInit
  // "EXCEPTION: No provider for Array!"
  constructor(
    booksByStoreID: Book[];
  ) {}


  ngOnInit() {
    this.booksByStoreID = this.books.filter(
      book => book.store_id === this.store.id);
  }
}

// ..omitted
Código-MonKy
fuente

Respuestas:

205

Necesita poner su código ngOnInity usar la thispalabra clave:

ngOnInit() {
  this.booksByStoreID = this.books.filter(
          book => book.store_id === this.store.id);
}

Lo necesita ngOnInitporque la entrada storeno se establecería en el constructor:

ngOnInit se llama justo después de que se hayan verificado las propiedades enlazadas a datos de la directiva por primera vez y antes de que se haya verificado cualquiera de sus hijos. Se invoca solo una vez cuando se crea una instancia de la directiva.

( https://angular.io/docs/ts/latest/api/core/index/OnInit-interface.html )

En su código, el filtrado de libros se define directamente en el contenido de la clase ...

Thierry Templier
fuente
Tiene sentido. Recibo el error "Error: ngOnInit no está definido" después de agregar su fragmento de código, importar OnInity agregar booksByStoreID = Book[];el componente.
Code-MonKy
Creo que es más bien:booksByStoreID: Book[];
Thierry Templier
Tampoco funciona. ¿Debería poner esto en un constructor tal vez? Intenté esto, luego ]
aparece
1
¡Gracias! El filtrado funciona completamente :) Sin embargo, surgió un nuevo problema. Al hacer clic en el componente principal de manera que se selecciona otra tienda, el antiguo store_id permanece y la lista de libros permanece igual ...
Code-MonKy
1
Excelente. felicidades por 200 votos !!!
Amuk Saxena
18

Puede comprobar un ejemplo en Plunker aquí filtros de ejemplo de plunker

filter() {

    let storeId = 1;
    this.bookFilteredList = this.bookList
                                .filter((book: Book) => book.storeId === storeId);
    this.bookList = this.bookFilteredList; 
}
yaircarreno
fuente
4

Para filtrar una matriz independientemente del tipo de propiedad (es decir, para todos los tipos de propiedad), podemos crear una tubería de filtro personalizada

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

@Pipe({ name: "filter" })
export class ManualFilterPipe implements PipeTransform {
  transform(itemList: any, searchKeyword: string) {
    if (!itemList)
      return [];
    if (!searchKeyword)
      return itemList;
    let filteredList = [];
    if (itemList.length > 0) {
      searchKeyword = searchKeyword.toLowerCase();
      itemList.forEach(item => {
        //Object.values(item) => gives the list of all the property values of the 'item' object
        let propValueList = Object.values(item);
        for(let i=0;i<propValueList.length;i++)
        {
          if (propValueList[i]) {
            if (propValueList[i].toString().toLowerCase().indexOf(searchKeyword) > -1)
            {
              filteredList.push(item);
              break;
            }
          }
        }
      });
    }
    return filteredList;
  }
}

//Usage

//<tr *ngFor="let company of companyList | filter: searchKeyword"></tr>

No olvide importar la tubería en el módulo de la aplicación.

Es posible que necesitemos personalizar la lógica para declarar con fechas.

alchi baucha
fuente