Búsqueda de sitios web

javascript - Angular Cómo filtrar datos de un arreglo buscando en un input


Cómo filtrar un objeto de array en texto de entrada - angular Estoy intentando hacer una barra de búsqueda para filtrar donde el usuario pueda buscar la ubicación/descripción, a la que llamé "sensor".

roomlist.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

{
    "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

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

En la función searchData, estoy tratando de hacer que filtre mientras se escribe basado en la ubicación/descripción, a la que le puse el nombre de "sensor".

Respuesta #1

Cada vez que haces una búsqueda, estás filtrando los elementos en tu array y dando la salida a tu array original. En consecuencia, pierdes tus datos. ¿Por qué no creas 2 variables:

  1. El arreglo original que no cambia (que contiene tus datos) debería estar en un proveedor, pero en nuestro ejemplo lo declararemos en tu componente.
  2. El arreglo filtrado que vas a mostrar
  searchData(searchValue: any) {
      this.filteredData = this.rowData.filter((item: templogRecord) => {
        return item.sensor.toLowerCase().includes(searchValue.toLowerCase());
      });
 }


Respuesta #2

Recomendaría esta solución (Basado en materiales de autocompletado: https://stackblitz.com/angular/lndebkoyare?file=app%2Fautocomplete-filter-example.ts)

En tu componente:

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

Tu plantilla se vería así:

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

Cada vez que el valor en la entrada cambia, el observable valueChanges en searchControl emite el valor actual de este campo de entrada. Esta parte map(value => this._filter(value)) devuelve un subconjunto filtrado de tu array de opciones, que puede ser mostrado usando el pipe async: <li class="cards__item" *ngFor="let data of filteredOptions | async">...</li>

Artículos relacionados