Wie filtere ich ein Array mit TypeScript in Angular 2?


108

Die Vererbung von Eltern-Kind-Daten von ng-2 war für mich eine Schwierigkeit.

Was anscheinend eine gut funktionierende praktische Lösung sein könnte, ist das Filtern meines gesamten Datenarrays in ein Array, das nur aus untergeordneten Daten besteht, auf die durch eine einzelne übergeordnete ID verwiesen wird. Mit anderen Worten: Die Datenvererbung wird zur Datenfilterung nach einer übergeordneten ID.

In einem konkreten Beispiel kann dies so aussehen: Filtern eines Bucharrays, um nur die Bücher mit einem bestimmten anzuzeigen 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 ist neu für mich, aber ich denke, ich bin kurz davor, die Dinge hier zum Laufen zu bringen.

(Auch das Überschreiben des ursprünglichen Bucharrays kann eine Option sein und dann verwendet werden *ngFor="#book of books".)

BEARBEITEN Näher dran , aber immer noch fehlerhaft.

//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

Antworten:


203

Sie müssen Ihren Code eingeben ngOnInitund das thisSchlüsselwort verwenden:

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

Sie benötigen, ngOnInitweil die Eingabe storenicht in den Konstruktor gesetzt werden würde:

ngOnInit wird direkt aufgerufen, nachdem die datengebundenen Eigenschaften der Direktive zum ersten Mal überprüft wurden und bevor eines ihrer untergeordneten Elemente überprüft wurde. Es wird nur einmal aufgerufen, wenn die Direktive instanziiert wird.

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

In Ihrem Code wird die Bücherfilterung direkt im Klasseninhalt definiert ...


Macht Sinn. Ich erhalte die Fehlermeldung "Fehler: ngOnInit ist nicht definiert", nachdem Sie Ihren Code OnInithinzugefügt, booksByStoreID = Book[];die Komponente importiert und hinzugefügt haben .
Code-MonKy

Ich denke, dass es eher ist:booksByStoreID: Book[];
Thierry Templier

Funktioniert auch nicht. Sollte ich das vielleicht in einen Konstruktor stecken? Ich habe es versucht, dann bekomme ich eine Fehlermeldung über den]
Code-MonKy

1
Vielen Dank! Die Filterung funktioniert vollständig :) Es ist jedoch ein neues Problem aufgetreten. Wenn Sie auf die übergeordnete Komponente klicken, sodass ein anderes Geschäft ausgewählt wird, bleibt die alte store_id erhalten und die Liste der Bücher bleibt gleich ...
Code-MonKy

1
Ausgezeichnet. Herzlichen Glückwunsch zu 200 Stimmen !!!
Amuk Saxena


4

Um ein Array unabhängig vom Eigenschaftstyp (dh für alle Eigenschaftstypen) zu filtern, können Sie eine benutzerdefinierte Filterpipe erstellen

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>

Vergessen Sie nicht, die Pipe in das App-Modul zu importieren

Möglicherweise müssen wir die Logik so anpassen, dass sie mit Datumsangaben versehen wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.