Home > Software design >  Angular Filtering Multiple Unordered Words
Angular Filtering Multiple Unordered Words

Time:02-01

In my code, I am trying to filter elements from a list and I'm trying to filter that element when I write multiple words at once. Right now, I can filter the element if I write the words in their correct order. For example; I can filter 'red book love' element if I write 'red book' but I also want to filter it when I write 'red love'. Here is my code, what should I do to achieve what I want?

HTML:

 <mat-form-field appearance="outline" fxFlex="100" >
            <mat-label>Product</mat-label>
            <input type="text" required matInput [(ngModel)]="product" name="product"
                (input)="onProductSearchChange($event.target.value)" [matAutocomplete]="autoProductId">
            <button mat-button matSuffix mat-icon-button aria-label="Clear" (click)="product = null" type="button">
                <mat-icon>block</mat-icon>
            </button>
            <mat-autocomplete autoActiveFirstOption #autoProductId="matAutocomplete"
                [displayWith]="displayProduct.bind(this)" (optionSelected)="filterProduct($event.option.value)">
                <mat-option *ngFor="let prm of productList" [value]="prm">
                    {{prm?.StockIntegrationCode  ' '  prm?.ProductName}}
                </mat-option>
            </mat-autocomplete>
        </mat-form-field>

TS:

onProductSearchChange(search: string) {
    let filterValue = (search as any).toLocaleLowerCase("tr");
    if (
        this._adminService.products &&
        this._adminService.products.length > 0
    ) {
        this.productList = this._adminService.products.filter(
            (x) =>
                x.StockIntegrationCode.indexOf(filterValue) >= 0 ||
                (x.ProductName as any)
                    .toLocaleLowerCase("tr")
                    .indexOf(filterValue) >= 0
        );
    }
    if (!search) {
        this.product = null;
        this.productList = this._adminService.products;
    }
}

displayProduct(product: IProduct): string | undefined {
    return product
        ? product.StockIntegrationCode   " - "   product.ProductName
        : "";
}

CodePudding user response:

I can't tell if you want ALL of the words to match, or just ONE of the words to match, so here's both solutions. I also have no idea what a stock integration code is, so I'm assuming it counts if there's a match in either the code or the name.

Just one word matches

  onProductSearchChange(search: string) {
    if (!search) {
      this.product = null;
      this.productList = this._adminService.products;
      return; //Return because the string is empty
    }
    let filterValue = search.toLocaleLowerCase('tr');
    let values = filterValue.split(' ');
    if (this._adminService.products && this._adminService.products.length > 0) {
      this.productList = this._adminService.products.filter((x) => {
        for (const value of values) {
          if (
            x.StockIntegrationCode.includes(value) ||
            x.ProductName.toLocaleLowerCase('tr').includes(value)
          )
            return true;
        }
        return false;
      });
    }
  }

All words match

  onProductSearchChange(search: string) {
    if (!search) {
      this.product = null;
      this.productList = this._adminService.products;
      return; //Return because the string is empty
    }
    let filterValue = search.toLocaleLowerCase('tr');
    let values = filterValue.split(' ');
    if (this._adminService.products && this._adminService.products.length > 0) {
      this.productList = this._adminService.products.filter((x) => {
        for (const value of values) {
          if (
            !x.StockIntegrationCode.includes(value) &&
            !x.ProductName.toLocaleLowerCase('tr').includes(value)
          )
            return false;
        }
        return true;
      });
    }
  }

I just split the filterValue on whitespace, and searched word by word.

  •  Tags:  
  • Related