首页 文章

如何在Angular 2中使用TypeScript过滤数组?

提问于
浏览
77

ng-2亲子数据继承对我来说一直是个难题 .

看起来可能是一个很好的实用解决方案是将我的整个数据数组过滤到一个数组,该数组只包含由单个父ID引用的子数据 . 换句话说:数据继承成为一个父ID的数据过滤 .

在一个具体的例子中,这可能看起来像:过滤书籍数组只显示具有某种 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 回答

  • 0

    要过滤数组而不考虑属性类型(即对于所有属性类型),我们可以创建自定义过滤器管道

    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>
    

    不要忘记在app模块中导入管道

    我们可能需要使用日期自定义文件管理器的逻辑 .

  • 139

    您需要将代码放入 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

    在您的代码中,书籍过滤直接定义到类内容中......

  • 9

    您可以在此处查看Plunker中的示例plunker example filters

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

相关问题