How do I filter an array with TypeScript in Angular 2?
Solution 1
You need to put your code into ngOnInit
and use the this
keyword:
ngOnInit() {
this.booksByStoreID = this.books.filter(
book => book.store_id === this.store.id);
}
You need ngOnInit
because the input store
wouldn't be set into the constructor:
ngOnInit is called right after the directive's data-bound properties have been checked for the first time, and before any of its children have been checked. It is invoked only once when the directive is instantiated.
(https://angular.io/docs/ts/latest/api/core/index/OnInit-interface.html)
In your code, the books filtering is directly defined into the class content...
Solution 2
You can check an example in Plunker over here plunker example filters
filter() {
let storeId = 1;
this.bookFilteredList = this.bookList
.filter((book: Book) => book.storeId === storeId);
this.bookList = this.bookFilteredList;
}
Solution 3
To filter an array irrespective of the property type (i.e. for all property types), we can create a custom filter 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>
Don't forget to import the pipe in the app module
We might need to customize the logic to filer with dates.
Code-MonKy
Updated on July 08, 2022Comments
-
Code-MonKy almost 2 years
ng-2 parent-child data inheritance has been a difficulty for me.
What seems that could be a fine working practical solution is filtering my total array of data to an array consisting of only child data referenced by a single parent id. In other words: data-inheritance becomes data filtering by one parent id.
In a concrete example this can look like: filtering a books array to only show the books with a certain
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 is new to me, but I think I am close to making things work here.
(Also overwriting the original books array could be an option, then using
*ngFor="#book of books"
.)EDIT Getting closer, but still giving an 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
-
Code-MonKy about 8 yearsMakes sense. I get the error "Error: ngOnInit is not defined" after adding your piece of code, importing
OnInit
and addingbooksByStoreID = Book[];
in the component. -
Thierry Templier about 8 yearsI think that it's rather:
booksByStoreID: Book[];
-
Code-MonKy about 8 yearsDoesn't work either. Should I puts this in a constructor maybe? I tried this, then I get an error complaining about the
]
-
Thierry Templier about 8 yearsCould you add in your question (in an edit paragraph for example) the code your tried? It's difficult for me to guess what you tried ;-) Thanks!
-
Code-MonKy about 8 yearsI seem to get a DI Exception, while before buidling the data filtering retrieving the store id wasn't a problem at all and printed in the template. Maybe you can find something I overlooked in my edit?
-
Thierry Templier about 8 yearsIt's because you should use this:
booksByAimID: Book[]; constructor() {}
. ``booksByAimID: Book[];` is a property declaration not a constructor parameter. Angular2 leverages constructor parameter for dependency injection... -
Code-MonKy about 8 yearsThanks! The filtering completly works :) A new issue arose though. When clicking in the parent component such that another store is selected, the old store_id remains and the list of books stay the same...
-
Thierry Templier about 8 yearsGreat! You need to implement
ngOnChanges
to detect this. Whenstore_id
will be updated, this method will be called and you can execute the same thing thanngOnInit
... -
Code-MonKy about 8 years
ngOnChanges(store) { this.store.id = store[id].currentValue };
leaves me with a "RefferenceError". Any idea? -
Thierry Templier about 8 yearsNot sure what you're trying to do ;-) I thought of this:
ngOnChanges() { this.booksByStoreID = this.books.filter( book => book.store_id === this.store.id); }
-
Code-MonKy about 8 yearsThanks, my app is functional :) I thought I could overwrite the input values since ngOnInit will be called after ngOnChanges. But maybe I misunderstood and this is the only way.
-
stackUser44 about 7 yearswhen I try this solution showing as " Cannot read property 'filter' of undefined"
-
Chanaka Amarasinghe almost 6 yearsin my case 'books' is an array and I need output also a array
-
sandeep about 4 yearsCan we put an OR (||) condition here like (book => book.store_id === 2|| book.store_id === 5) ?