简体   繁体   English

Angular 如何通过在输入中搜索来过滤数组数据

[英]Angular How to filter array data by searching in input

How to filter an array object in input text - angular I'm trying to make an search bar to filter where the user can search the location/description which I name it "sensor".如何过滤输入文本中的数组对象 - angular 我正在尝试制作一个搜索栏来过滤用户可以搜索我将其命名为“传感器”的位置/描述的位置。

roomlist.component.ts房间列表.component.ts

  validateForm: FormGroup;
  rowData: templogRecord[] = [];
  option: any = [];

  onLoad() {
    this.rowData = record.default.records;

    this.option = [];

    this.rowData.forEach(room => {
      this.option.push({
        tooltip: {
          formatter: "{a} <br/>{b} : {c}°"
        },
        toolbox: {
          show: true,
          feature: {
            mark: { show: false },
            restore: { show: false },
            saveAsImage: { show: false }
          }
        },
        series: [
          {
            name: room.sensor,
            type: 'gauge',
            center: ['40%', '70%'],
            splitNumber: 10,
            radius: '70%',
            axisLine: {
              lineStyle: {
                color: [[0.2, '#48b'], [0.8, '#228b22'], [1, '#ff0000']],
                width: 8
              }
            },
            axisTick: {
              splitNumber: 10,
              length: 12,
              lineStyle: {
                color: 'auto'
              }
            },
            axisLabel: {
              textStyle: {
                color: 'auto'
              }
            },
            splitLine: {
              show: true,
              length: 30,
              lineStyle: {
                color: 'auto'
              }
            },
            pointer: {
              width: 5
            },
            title: {
              show: true,
              offsetCenter: [0, '65%'],
              textStyle: {
                fontWeight: 'bolder'
              }
            },
            detail: {
              formatter: '{value}°',
              textStyle: {
                color: 'auto',
                fontWeight: 'bolder'
              }
            },
            data: [{ value: this.tempGenerator(), name: "Temperature" }]
          },
          {
            name: '转速',
            type: 'gauge',
            center: ['70%', '25%'],
            splitNumber: 10,
            radius: '40%',
            axisLine: {
              lineStyle: {
                width: 8
              }
            },
            axisTick: {
              length: 12,
              lineStyle: {
                color: 'auto'
              }
            },
            splitLine: {
              length: 20,
              lineStyle: {
                color: 'auto'
              }
            },
            pointer: {
              width: 5
            },
            title: {
              show: true,
              offsetCenter: [0, '80%'],
              textStyle: {
                fontWeight: 'bolder',
              }
            },
            detail: {
              formatter: '{value}%',
              offsetCenter: [0, '55%'],
              textStyle: {
                color: 'auto',
                fontSize: 18,
                fontWeight: 'bolder'
              }
            },
            data: [{ value: 1.5, name: "Humidity" }]
          }
        ]
      });
    });
  }

  tempGenerator() {

    var time = 12;

    var num = Math.random() * 100;

    var tempBase = Math.round(num);

    var fluc = [0, 1, 1, 2, 1, 1, 2.5, 3.5, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];

    return tempBase * fluc[time];
  }

  searchData(searchValue: any) {
    if (searchValue.length >= 3) {
      this.rowData = this.rowData.filter((data: templogRecord) => {
        console.log(data['sensor']);
      });
    } else if (searchValue.length < 1) {
      console.log('empty')
    }
 }
}

roomlist.json房间列表.json

{
    "records": [
        {
            "dateandtime": "2018-06-14 02:24:02",
            "sensor": "Nine Seal Area",
            "temperature": "25.9",
            "humidity": "99.9"
        },
        {
            "dateandtime": "2018-06-14 02:24:02",
            "sensor": "Ten Line2",
            "temperature": "25.9",
            "humidity": "99.9"
        },
        {
            "dateandtime": "2018-06-14 02:22:01",
            "sensor": "Eight Line1",
            "temperature": "25.9",
            "humidity": "99.9"
        }
    ]
}

room-list.component.html房间列表.component.html

<div class="flex-container">
    <div class="date-filter">
      <nz-input-group [nzSuffix]="suffixIconSearch">
        <input type="text" 
          nz-input placeholder="Search" 
          [(ngModel)]="filterSearch" 
          (ngModelChange)="searchData($event)"
          />
      </nz-input-group>
      <ng-template #suffixIconSearch>
        <i nz-icon nzType="search"></i>
      </ng-template>
    </div>
    <ul class="cards">
      <li class="cards__item" *ngFor="let data of option">
        <div class="card">
          <div echarts [options]="data" [autoResize]="true"></div>
          <div class="card__content">
            <button class="btn btn--block card__btn">Button</button>
          </div>
        </div>
      </li>
    </ul>
  </div>

In the searchData function, I'm trying to make it filtering while typing based in location/description which I named it "sensor".searchData函数中,我试图在根据我将其命名为“传感器”的位置/描述进行键入时对其进行过滤。

Each time you make a search, you're filtering the elements in your array and giving the output to your original array.每次进行搜索时,都会过滤数组中的元素并将输出提供给原始数组。 Consequently, you loose your data.因此,您会丢失数据。 Why don't you create 2 variables:为什么不创建 2 个变量:

  1. The original array which doesn't change ( containing your data ) which should be in a provider but in our example we'll declare it in your component.不改变的原始数组(包含您的数据)应该在提供者中,但在我们的示例中,我们将在您的组件中声明它。
  2. The filtered array which you're going to display您将要显示的过滤后的数组
  searchData(searchValue: any) {
      this.filteredData = this.rowData.filter((item: templogRecord) => {
        return item.sensor.toLowerCase().includes(searchValue.toLowerCase());
      });
 }


I would recommend this solution (Based on materials autocomplete: https://stackblitz.com/angular/lndebkoyare?file=app%2Fautocomplete-filter-example.ts )我会推荐这个解决方案(基于材料自动完成: https : //stackblitz.com/angular/lndebkoyare? file = app%2Fautocomplete-filter- example.ts

In your component:在您的组件中:

import {Component, OnInit} from '@angular/core';
import {FormControl} from '@angular/forms';
import {Observable} from 'rxjs';
import {map, startWith} from 'rxjs/operators';

/**
 * @title Filter autocomplete
 */
@Component({
  selector: 'autocomplete-filter-example',
  templateUrl: 'autocomplete-filter-example.html',
  styleUrls: ['autocomplete-filter-example.css'],
})
export class FilterExample implements OnInit {

  // your control for input
  searchControl = new FormControl();

  // your whole set of options
  options: string[] = ['One', 'Two', 'Three'];

  // your current result based on filters input
  filteredOptions: Observable<string[]>;

  ngOnInit() {
    this.filteredOptions = this.searchControl.valueChanges
      .pipe(
        startWith(''),
        map(value => this._filter(value))
      );
  }

  private _filter(value: string): string[] {
    const filterValue = value.toLowerCase();

    return this.options.filter(option => option.toLowerCase().includes(filterValue));
  }
}

Your template would look like this:您的模板如下所示:

<div class="flex-container">
<div class="date-filter">
  <nz-input-group [nzSuffix]="suffixIconSearch">
    <input type="text" 
      nz-input placeholder="Search" 
      [formControl]="searchControl"
      />
  </nz-input-group>
  <ng-template #suffixIconSearch>
    <i nz-icon nzType="search"></i>
  </ng-template>
</div>
<ul class="cards">
  <li class="cards__item" *ngFor="let data of filteredOptions | async">
    <div class="card">
      <div echarts [options]="data" [autoResize]="true"></div>
      <div class="card__content">
        <button class="btn btn--block card__btn">Button</button>
      </div>
    </div>
  </li>
</ul>

Every time value on input changes the observable valueChanges on searchControl emits the current value of this input field.每次输入上的值更改searchControl上的可观察valueChangessearchControl发出此输入字段的当前值。 This part map(value => this._filter(value)) returns a filtered subset of your options array.这部分map(value => this._filter(value))返回选项数组的过滤子集。 Which can be displayd using the async pipe: <li class="cards__item" *ngFor="let data of filteredOptions | async">...</li>可以使用异步管道显示: <li class="cards__item" *ngFor="let data of filteredOptions | async">...</li>

DO NOT USE find or includes , because these are not supported by the Internet Explorer.不要使用findincludes ,因为 Internet Explorer 不支持这些。

How about using javascript's filter function?使用javascript的filter功能怎么样? See an example below.请参阅下面的示例。

The following example assumes that you are targeting the sensor element in the object.下面的示例假设您以对象中的sensor元素为目标。

Click here for a DEMO单击此处查看演示

 const test = {
    "records": [
        {
            "dateandtime": "2018-06-14 02:24:02",
            "sensor": "Nine Seal Area",
            "temperature": "25.9",
            "humidity": "99.9"
        },
        {
            "dateandtime": "2018-06-14 02:24:02",
            "sensor": "Ten Line2",
            "temperature": "25.9",
            "humidity": "99.9"
        },
        {
            "dateandtime": "2018-06-14 02:22:01",
            "sensor": "Eight Line1",
            "temperature": "25.9",
            "humidity": "99.9"
        }
    ]
};

let found = [];
const searchTerm = 'Eight Line1';
found = test.records.filter(function(element) {
  return element.sensor.toLowerCase() == searchTerm.toLowerCase();
});

console.log('found ' , found[0]);

Update更新

To perform a partial search (searching for a part of the string), you can safely use indexOf .要执行部分搜索(搜索字符串的一部分),您可以安全地使用indexOf See an example below,看下面的例子,

console.log("Eight Line1".indexOf("Ei") !== -1); 

Hope this helps,希望这可以帮助,

Thanks.谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM