【问题标题】:How to filter objects using multiple conditions from an array?如何使用数组中的多个条件过滤对象?
【发布时间】:2019-09-23 01:17:33
【问题描述】:

我正在为 Angular 组件中的发票表设置几个过滤器。一个是与来自 invoices 数组的发票模型的属性名称匹配的搜索输入,另一个是来自下拉选择元素的“状态”过滤器。

这个新过滤器只会在“statusFilter”(ngModel)不等于 0 时运行,因为 0 是默认值,意味着显示所有忽略发票的状态。我能够成功地单独过滤每个条件,但是当尝试在一个过滤器函数中添加这两个条件时,callbackfn 总是返回 false。

现在,只有在搜索输入中输入一个值后,我才能从过滤器中获得真正的结果。

HTML

<select [(ngModel)]="statusFilter" (change)="updateFilter($event)">
  <option [value]="0">Show All</option>
  <option [value]="4">Paid</option>
  <option [value]="1">Outstanding</option>
  <option [value]=8>Cancelled</option>
</select>
....
<label>Search:
 <input (keyup)="updateFilter($event)" class="form-control form-control-sm" placeholder="search by name.." type="search">
</label>

组件

export class CompanyInvoicesComponent implements OnInit {
  public isLoading: boolean;
  public limit = 10;
  public temp = [];
  public selected = [];
  public invoice: Invoice;
  public statusFilter: number = 0;
  public rows: Invoice[];

  @ViewChild(DatatableComponent) table: DatatableComponent;


  constructor(
    private _appService: AppService,
    private _invoiceService: InvoiceService,
  ) {

    this._invoiceService.companyInvoices()
      .subscribe( (invoices) => {
        const invoicesArr = [];
        for (const invoice of invoices) {
          invoicesArr.push(new Invoice(invoice, true));
        }

        this.rows = invoicesArr;
        this.temp = [...invoicesArr];
        this._appService.toggleLoading(false);
      });
  }


  updateFilter(event) {
    const val = event.target.value.toLowerCase();
    let temp = this.temp.filter((invoice) => {

      // the type number is lost after value is changed.
      const parsedStatusFilter = parseInt(this.statusFilter.toString(), 10);
      console.log(parsedStatusFilter);
      if (parsedStatusFilter == 0) {
        return (invoice.name.toLowerCase().indexOf(val) !== -1 || !val);
      } else {
        return (parsedStatusFilter == invoice.statusNumber) && (invoice.name.toLowerCase().indexOf(val) !== -1 || !val);
      }
    });

    // update the rows
    this.rows = temp;
    // Whenever the filter changes, always go back to the first page
    this.table.offset = 0;
  }

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    我会为搜索值(来自输入)使用附加属性来在过滤时保存它,因为过滤使用相同的方法,您需要同时保存 statusFilter 和搜索值。还要检查第一个过滤器中字符串的length

    组件:

    statusFilter = 0;
    searchingWord = '';
    
    updateFilter(event) {
      const val = this.searchingWord.toLowerCase();
      const parsedStatusFilter = parseInt(this.statusFilter.toString(), 10);
    
      const temp = this.temp.filter((invoice) => {
    
        if (parsedStatusFilter == 0) {
          return (!val.length || invoice.name.toLowerCase().indexOf(val) !== -1);
        } else {
          return (parsedStatusFilter == invoice.statusNumber) && (!val.length || invoice.name.toLowerCase().indexOf(val) !== -1);
        }
      });
      // filtered temp
      console.log('temp', temp);
    }
    

    HTML 模板:

    <select [(ngModel)]="statusFilter" (change)="updateFilter($event)">
      <option [value]="0">Show All</option>
      <option [value]="4">Paid</option>
      <option [value]="1">Outstanding</option>
      <option [value]=8>Cancelled</option>
    </select>
    <label for="search-box">Search:</label>
    <input input name="search-box" id="search-box" [(ngModel)]='searchingWord' (keyup)="updateFilter($event)" class="form-control form-control-sm" placeholder="search by name.." type="search">
    

    stackblitz

    【讨论】:

    • 太棒了,你指出了我错过了什么。我没有注意到 val 可能被其他输入覆盖。这是我的错误。 const val = event.target.value.toLowerCase(); 我检查了实际代码中的长度,不知何故我在问题上省略了它。谢谢!
    猜你喜欢
    • 2021-07-05
    • 1970-01-01
    • 2022-11-30
    • 2023-02-07
    • 2018-04-19
    • 2019-10-17
    • 1970-01-01
    • 1970-01-01
    • 2022-11-27
    相关资源
    最近更新 更多