角度搜索过滤器管道,用于完整句子搜索,而与单词顺序无关

时间:2019-04-30 08:39:15

标签: angular typescript

我想制作一个搜索栏,可以从下表中搜索“标题”,与该句子中单词的顺序无关

我尝试实现一个过滤器管道,该管道检查标题中是否存在搜索字符串。 我还尝试将数组中的两个字符串拆分并循环遍历以检查公共字段。

基本上,我希望在“三星Metro”和“大都会三星”上获得相同的结果

下面是工作产品和问题的GIF的链接。

https://user-images.githubusercontent.com/26569942/56949597-f8f6f280-6b50-11e9-8521-bfd1235126d9.gif

感谢您的帮助。

///////////////////////
//home.component.html//
///////////////////////

<div class="form-group">
  <input type="text" [(ngModel)]="searchTerm">  
</div>
<div class="row">

  <table class="table table-striped col-12" >
    <thead>
      <tr>
        <th scope="col">Title</th>
        <th scope="col">Price</th>
        <th scope="col">Popularity</th>
        <th scope="col">Subcategory</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let item of products | keyvalue | productFilter : searchTerm">
        <th scope="row">{{item.value.title}}</th>
        <td>{{item.value.price}}</td>
        <td>{{item.value.popularity}}</td>
        <td>{{item.value.subcategory}}</td>
      </tr>
    </tbody>
  </table>

</div>
/////////////////////
//home.component.ts//
/////////////////////

export class HomeComponent implements OnInit {

  jsonData: any;
  products: any;
  count: number;
  searchTerm: string;

  constructor(private data: DataService) { }

  ngOnInit() {
    this.data.getData().subscribe(
      (t: any) => {
        this.products = t.products;
        this.count = t.count;
      }
    );
  }
}
//////////////////////////
//product-filter.pipe.ts//
//////////////////////////

import { PipeTransform, Pipe } from '@angular/core';

@Pipe({
    name: 'productFilter'
})

export class ProductFilterPipe {
    transform(products: any[], searchTerm: string) {

        if (!products || !searchTerm) {
            return products;
        }

        return products.filter(function (product) {

            return product.value.title.toLowerCase().includes(searchTerm.toLowerCase());

            // Below commented code is my failed try
            // product.value.title.toLowerCase().split(" ").filter( item => {
            //     searchTerm.toLowerCase().split(" ").includes(item);
            // })

        });
    }
}
////////////////////////
//data looks like this//
////////////////////////
{
    "count": 3,
    "products": {
      "6834": {
        "subcategory": "mobile",
        "title": "Micromax Canvas Spark",
        "price": "4999",
        "popularity": "51936"
      },
      "5530": {
        "subcategory": "mobile",
        "title": "Samsung Galaxy Grand Max",
        "price": "12950",
        "popularity": "48876"
      },
      "4340": {
        "subcategory": "mobile",
        "title": "Apple iPhone 6",
        "price": "40999",
        "popularity": "46198"
      }
    }
}

2 个答案:

答案 0 :(得分:0)

您可以从搜索字符串中创建一个正则表达式,并根据您的数据对其进行测试:

new RegExp(['Galaxy', 'Samsung'].map(s => `(?=.*?${s})`).join('') + '.*').test('Samsung Galaxy');

因此,在您的情况下,请分割搜索词并测试product.value.title:

new RegExp(searchTerm.split(' ').map(s => `(?=.*?${s})`).join('') + '.*').test(product.value.title);

答案 1 :(得分:0)

想出了像这样的东西。

import { PipeTransform, Pipe } from '@angular/core';

@Pipe({
    name: 'productFilter'
})

export class ProductFilterPipe {
    transform(products: any[], searchTerm: string) {

        if (!products || !searchTerm) {
            return products;
        }

        return ProductFilterPipe.filter(products, searchTerm);
    }

    static filter(products: Array<{ [key: string]: any }>, searchTerm: string): Array<{ [key: string]: any }> {

        return products.filter(function (product: any) {
            return searchTerm.trim().toLowerCase().split(" ").some(r=> product.value.title.toLowerCase().indexOf(r) >= 0)
        });
    }
}