Как отфильтровать массив с помощью TypeScript в Angular 2?
ng-2 наследование данных родитель-ребенок было проблемой для меня.
то, что кажется, что может быть прекрасным рабочим практическим решением, - это фильтрация моего общего массива данных в массив, состоящий только из дочерних данных, на которые ссылается один родительский идентификатор. Другими словами: наследование данных становится фильтрацией данных по одному родительскому идентификатору.
в конкретном примере это может выглядеть так: фильтрация книг массив, чтобы показывать только книги с определенным 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 является новым для меня, но я думаю, что я близок к тому, чтобы заставить вещи работать здесь.
(также перезапись исходного массива книг может быть опцией, а затем с помощью *ngFor="#book of books"
.)
EDIT Приближаясь, но все же давая ошибку.
//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
3 ответа:
вы должны поместить ваш код в
ngOnInit
и с помощьюthis
ключевые слова:ngOnInit() { this.booksByStoreID = this.books.filter( book => book.store_id === this.store.id); }
вам нужно
ngOnInit
потому что входstore
не будет установлен в конструктор:ngOnInit вызывается сразу после того, как свойства директивы, связанные с данными, были проверены в первый раз, и до того, как был проверен любой из его дочерних элементов. Он вызывается только один раз, когда директива создать экземпляр.
(https://angular.io/docs/ts/latest/api/core/index/OnInit-interface.html)
в вашем коде фильтрация книг непосредственно определяется в содержимом класса...
вы можете проверить пример в Plunker здесь plunker пример фильтров
filter() { let storeId = 1; this.bookFilteredList = this.bookList .filter((book: Book) => book.storeId === storeId); this.bookList = this.bookFilteredList; }
чтобы фильтровать массив независимо от типа свойства (т. е. для всех типов свойств), мы можем создать пользовательский фильтр pipe
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>
Не забудьте импортировать трубу в модуль приложения
нам может потребоваться настроить логику для файла с датами.