web-dev-qa-db-fra.com

Comment implémenter la recherche et le filtrage dans Ionic

Je récupère des données à partir d'un fichier JSON stocké localement dans mon projet. La chaîne JSON est un tableau d'emplacements, dont la structure est la suivante:

fichier JSON

{
    "locations": [
        {
            "title": "ABC",
            "latitude": -1.2596551,
            "longitude": 36.7066604,
            "routes":["22","23","105","115"],
            "fare":[],
            "matatu":[]
        },
        {
            "title": "Adams Arcade",
            "latitude": -1.3004204,
            "longitude": 36.7770793,
            "routes": ["2","4W","102","24","24C","111"],
            "fare":[],
            "matatu":[]
        },
        {
            "title":"Aga Khan Hospital",
            "latitude":-1.2620125,
            "longitude":36.8186399,
            "routes":["11A","11F","106","107","116"],
            "fare":[],
            "matatu":[]
        }
    ]
}

Plutôt que de filtrer les données à la volée avec un tuyau, j'ai implémenté une fonction dans mon provider pour gérer cela. Voici le code:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
import { Geolocation } from '@ionic-native/geolocation';

@Injectable()
export class LocationProvider {

  data: any;

  constructor(public http: Http, public geolocation: Geolocation) {

  }

  load(){

    if(this.data){
      return Promise.resolve(this.data);
    }

    return new Promise(resolve => {
        this.http.get('assets/data/locations.json').map(res => res.json()).subscribe(data => {
          this.data = this.applyHarvesine(data.locations);
          this.data.sort((locationA, locationB) => {
            return locationA.distance - locationB.distance;
          });
          resolve(this.data);
        });
    });

  }

  filterLocations(searchTerm){
    return this.data.filter((location) => {
      return location.title.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1;
    });
  }

}

La fonction filterLocations() consiste à prendre searchTerm et retourne un tableau contenant uniquement les éléments qui correspondent aux critères de recherche.

Voici le code .ts Et .html Pour la page où il est rendu.

. ts

import { Component } from '@angular/core';
import { IonicPage, NavController } from 'ionic-angular';
import { LocationProvider } from '../../providers/location/location';
import { PlaceDetailsPage } from '../place-details/place-details';


@IonicPage()
@Component({
  selector: 'page-places',
  templateUrl: 'places.html',
})
export class PlacesPage {

  searchTerm: string = '';



  constructor(public navCtrl: NavController, public locations: LocationProvider) {
  }

  ionViewDidLoad() {
    this.setFilteredLocations();
  }

  setFilteredLocations(){
    return this.locations.filterLocations(this.searchTerm);
  }

}

. html

<ion-content>
    <ion-searchbar [(ngModel)]="searchTerm" (ionInput)="setFilteredLocations()"></ion-searchbar>
    <ion-list no-lines>
        <button ion-item *ngFor="let location of locations.data">
            <ion-avatar item-left>
                <ion-icon name="pin"></ion-icon>
            </ion-avatar>
            <h2>{{location.title}}</h2>
            <p>{{location.distance}} km</p>
        </button>
    </ion-list>
</ion-content>

Lorsque l'utilisateur tape dans la barre de recherche, setFilteredLocation() est appelée pour déclencher le filtrage des données. Le problème est que rien ne se passe.

Où ai-je mal tourné? Mon intuition est que quelque chose ne va pas dans la fonction setFilteredLocation(), mais je n'ai aucune idée de ce que c'est.

Existe-t-il une approche alternative à la recherche et au filtrage qui n'implique pas de tuyaux?

4
mondieki

Tu le fais incorectement.

  1. Vous faites return this.data.filter(...). Cela n'a aucun effet sur votre tableau Origin (this.data). Il retourne simplement un nouveau tableau et ne modifie pas this.data. Voir le filtre fonction doc
  2. Si vous souhaitez modifier vos données, vous devez ajouter: this.data = this.data.filter(...). Mais si vous aimez ça, vous tomberez dans une autre erreur. Votre this.data Perdra un élément après le filtre et il ne pourra pas être rétabli lorsque vous réinitialisez le filtre.

Vous devriez donc faire comme ça:
Dans votre composant:

allData = []; //Store all data from provider
filterData = [];//Store filtered data

ionViewDidEnter(){
  this.allData = this.locations.data;
  this.filterData = this.allData;
}

setFilteredLocations(){
    this.filterData = this.allData.filter((location) => {
      return location.title.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1;
    });
}

Et dans votre modèle, utilisez filterData dans ngFor:

<button ion-item *ngFor="let location of filterData">
10
Duannx

Yo n'a pas envoyé le $event ici. Essayez donc comme indiqué ci-dessous.

. html

 <ion-searchbar [(ngModel)]="searchTerm" 
(ionInput)="setFilteredLocations($event)"></ion-searchbar>

. ts

 setFilteredLocations(ev: any){
    let val = ev.target.value;

    if (val && val.trim() !== '') {
      return this.locations.filterLocations(val);
    }

  }

Vous pouvez voir le exemple de code officiel ici .

2
Sampath

Créer un tuyau à l'aide de la commande CLI et copier le code ci-dessous

transform(names: any[], terms: string): any[] {
if(!names) return [];
if(!terms) return names;
terms = terms.toLowerCase();
return names.filter( it => {
  return it.name.toLowerCase().includes(terms);
});

}

Pour plus d'informations https://androiddhina.blogspot.com/2019/03/ionic-4-search-filter-using-pipe.html

0
Dhina k