2

I'm setting up a couple of filters for an invoices table in an Angular component. One is a search input that matches with the property name of an invoice model from an invoices array the other one is a "status" filter from a drop-down select element.

this new filter will only run when the "statusFilter" (ngModel) is not equal to 0, since 0 is the default and means to show all ignoring the status of the invoice. I am successfully able to filter each condition individually but when trying to add both conditions within one filter function the callbackfn always returns false.

Right now, only after enter a value in the search input is when I get true results from the filter.

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>

Component

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;
  }

1 Answer 1

0

I'd use additional property for searched value (from input) to save it while filtering because for filtering the same method is used, and you need to save both statusFilter and searched value. Also check for length of string in first filter:

Component:

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 template:

<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

Sign up to request clarification or add additional context in comments.

1 Comment

Awesome, you pointed out what I had missed. I hadn't notice that val was probably getting overwritten by the other input. Here was my mistake. const val = event.target.value.toLowerCase(); I had checked for lenght in the actual code, somehow I omitted it on the question. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.