web-dev-qa-db-fra.com

Angular 4 Filtre de tuyau

J'essaie d'utiliser un canal personnalisé pour filtrer ma boucle *ngFor à l'aide d'un champ d'entrée avec ngModel. Avec mon autre tuyau personnalisé (sortBy), cela fonctionne parfaitement. Cependant, le filtre semble faire en sorte qu'aucune donnée n'apparaisse. J'apprends toujours cela et j'ai essayé quelques variantes en vain:

-filter: term
-filter: {{term}}
-filter: 'term'
-filter" {{'term'}}

Je pense donc que le problème se situe peut-être ailleurs dans le code. Si quelqu'un pouvait aider, je l'apprécierais vraiment.

Voici mon code:

Composant HTML

<div style="text-align:center">
  <h1>
    Welcome to {{title}}!!
  </h1>

</div>
<h2>Please choose your favorite song: </h2>
<form id="filter">
    <label>Filter people by name:</label>
    <input type="text" name="term" [(ngModel)]="term" />
</form>


<table class="table">
    <thead>
      <tr>
        <th>Title</th>
        <th>Artist</th>
        <th>Likes</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let song of songs | filter:term| sortBy: 'likes'; let i  = index">
        <td>{{song.title}}</td>
        <td>{{song.artist}}</td>
        <td>{{song.likes}} 

            <i class="fa fa-heart-o" aria-hidden="true"  *ngIf="song.likes < 1"></i>
         <i class="fa fa-heart" aria-hidden="true" *ngIf="song.likes >= 1"></i>
             <i class="fa fa-plus" aria-hidden="true" (click)="addLike(i)" ></i>
            <i class="fa fa-minus" aria-hidden="true" (click)="removeLike(i)" ></i>

          </td>
      </tr>
    </tbody>
  </table>

PIPE

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

@Pipe({
    name: 'filter',
    pure: false
})

export class FilterPipe implements PipeTransform {
    transform(items: any[], args: any[]): any {
        return items.filter(item => item.id.indexOf(args[0]) !== -1);
    }
}

Module

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { SortByPipe } from './sort-by.pipe';
import { FilterPipe } from './filter.pipe';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Pipe, PipeTransform } from '@angular/core'; 


@NgModule({
  declarations: [
    AppComponent,
    SortByPipe,
   FilterPipe
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

JS COMPOSANT

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'Oxcord';
  songs = [

  {title: "Song", artist: "Artist", likes: 1},
  {title: "Chanson", artist: "Artiste", likes: 3},
  {title: "ABC", artist: "OneTwoThree", likes: 2},
  {title: "Trash", artist: "Meek Mill", likes: 0}

  ];
  addLike(input){
  this.songs[input].likes +=1;
} 
removeLike(input){
  this.songs[input].likes -=1;
} 
args="Me";
}
24
user3523602

Voici un plan de travail avec un filtre et un tuyau de tri. https://plnkr.co/edit/vRvnNUULmBpkbLUYk4uw?p=preview

En tant que développeur033 mentionné dans un commentaire, vous transmettez une valeur unique au filtre, lorsque celui-ci attend un tableau de valeurs. Je dirais au tuyau d'attendre une valeur unique au lieu d'un tableau

export class FilterPipe implements PipeTransform {
    transform(items: any[], term: string): any {
        // I am unsure what id is here. did you mean title?
        return items.filter(item => item.id.indexOf(term) !== -1);
    }
}

Je conviens avec DeborahK que les tuyaux impurs doivent être évités pour des raisons de performances. Le plunkr comprend des journaux de console où vous pouvez voir combien le tuyau impur est appelé.

20
LLai

La signature de la méthode de transformation a été modifiée quelque part dans un RC de Angular 2. Essayez quelque chose de plus semblable à ceci:

export class FilterPipe implements PipeTransform {
    transform(items: any[], filterBy: string): any {
        return items.filter(item => item.id.indexOf(filterBy) !== -1);
    }
}

Et si vous souhaitez gérer les valeurs NULL et rendre le filtre insensible à la casse, vous souhaiterez peut-être faire quelque chose de plus semblable à celui que j'ai ici:

export class ProductFilterPipe implements PipeTransform {

    transform(value: IProduct[], filterBy: string): IProduct[] {
        filterBy = filterBy ? filterBy.toLocaleLowerCase() : null;
        return filterBy ? value.filter((product: IProduct) =>
            product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1) : value;
    }
}

Et NOTE: Le tri et le filtrage dans les tuyaux sont un gros problème de performances et ils ne sont pas recommandés ET PAS. Voir la documentation ici pour plus d'informations: https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe

10
DeborahK

Pipes in Angular 2+ constituent un excellent moyen de transformer et de formater des données directement à partir de vos modèles.

Les pipes nous permettent de changer les données à l'intérieur d'un template; filtrer, ordonner, formater des dates, des nombres, des devises, etc. Un exemple rapide est que vous pouvez transférer une chaîne en minuscule en appliquant un simple filtre dans le code du modèle.

Liste des tuyaux intégrés de Liste d'API Exemples

_{{ user.name | uppercase }}
_

Exemple de Angular version 4.4.7. _ng version_


Custom Pipes qui accepte plusieurs arguments.

_HTML « *ngFor="let student of students | jsonFilterBy:[searchText, 'name'] "
TS   « transform(json: any[], args: any[]) : any[] { ... }
_

Filtrer le contenu à l'aide d'un tuyau "_json-filter-by.pipe.ts_

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

@Pipe({ name: 'jsonFilterBy' })
@Injectable()
export class JsonFilterByPipe implements PipeTransform {

  transform(json: any[], args: any[]) : any[] {
    var searchText = args[0];
    var jsonKey = args[1];

    // json = undefined, args = (2) [undefined, "name"]
    if(searchText == null || searchText == 'undefined') return json;
    if(jsonKey    == null || jsonKey    == 'undefined') return json;

    // Copy all objects of original array into new Array.
    var returnObjects = json;
    json.forEach( function ( filterObjectEntery ) {

      if( filterObjectEntery.hasOwnProperty( jsonKey ) ) {
        console.log('Search key is available in JSON object.');

        if ( typeof filterObjectEntery[jsonKey] != "undefined" && 
        filterObjectEntery[jsonKey].toLowerCase().indexOf(searchText.toLowerCase()) > -1 ) {
            // object value contains the user provided text.
        } else {
            // object didn't match a filter value so remove it from array via filter
            returnObjects = returnObjects.filter(obj => obj !== filterObjectEntery);
        }
      } else {
        console.log('Search key is not available in JSON object.');
      }

    })
    return returnObjects;
  }
}
_

Ajoutez à @NgModule "Ajoutez JsonFilterByPipe à la liste de vos déclarations dans votre module; si vous oubliez de le faire, vous obtiendrez une erreur no fournisseur pour jsonFilterBy. Si vous ajoutez au module, il est disponible pour tous les composants de ce module.

_@NgModule({
  imports: [
    CommonModule,
    RouterModule,
    FormsModule, ReactiveFormsModule,
  ],
  providers: [ StudentDetailsService ],
  declarations: [
    UsersComponent, UserComponent,

    JsonFilterByPipe,
  ],
  exports : [UsersComponent, UserComponent]
})
export class UsersModule {
    // ...
}
_

Nom du fichier: _users.component.ts_ et StudentDetailsService est créé à partir de ce lien .

_import { MyStudents } from './../../services/student/my-students';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { StudentDetailsService } from '../../services/student/student-details.service';

@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: [ './users.component.css' ],

  providers:[StudentDetailsService]
})
export class UsersComponent implements OnInit, OnDestroy  {

  students: MyStudents[];
  selectedStudent: MyStudents;

  constructor(private studentService: StudentDetailsService) { }

  ngOnInit(): void {
    this.loadAllUsers();
  }
  ngOnDestroy(): void {
    // ONDestroy to prevent memory leaks
  }

  loadAllUsers(): void {
    this.studentService.getStudentsList().then(students => this.students = students);
  }

  onSelect(student: MyStudents): void {
    this.selectedStudent = student;
  }

}
_

Nom du fichier: _users.component.html_

_<div>
    <br />
    <div class="form-group">
        <div class="col-md-6" >
            Filter by Name: 
            <input type="text" [(ngModel)]="searchText" 
                   class="form-control" placeholder="Search By Category" />
        </div>
    </div>

    <h2>Present are Students</h2>
    <ul class="students">
    <li *ngFor="let student of students | jsonFilterBy:[searchText, 'name'] " >
        <a *ngIf="student" routerLink="/users/update/{{student.id}}">
            <span class="badge">{{student.id}}</span> {{student.name | uppercase}}
        </a>
    </li>
    </ul>
</div>
_
1
Yash

Je sais que c'est vieux, mais je pense avoir une bonne solution. En comparant avec d'autres réponses et en comparant avec accepté, le mien accepte plusieurs valeurs. Fondamentalement, filtrer objet avec les paramètres de recherche clé: valeur (également objet dans objet). En outre, cela fonctionne avec les nombres, etc., car lors de la comparaison, il les convertit en chaîne.

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

@Pipe({name: 'filter'})
export class Filter implements PipeTransform {
    transform(array: Array<Object>, filter: Object): any {
        let notAllKeysUndefined = false;
        let newArray = [];

        if(array.length > 0) {
            for (let k in filter){
                if (filter.hasOwnProperty(k)) {
                    if(filter[k] != undefined && filter[k] != '') {
                        for (let i = 0; i < array.length; i++) {
                            let filterRule = filter[k];

                            if(typeof filterRule === 'object') {
                                for(let fkey in filterRule) {
                                    if (filter[k].hasOwnProperty(fkey)) {
                                        if(filter[k][fkey] != undefined && filter[k][fkey] != '') {
                                            if(this.shouldPushInArray(array[i][k][fkey], filter[k][fkey])) {
                                                newArray.Push(array[i]);
                                            }
                                            notAllKeysUndefined = true;
                                        }
                                    }
                                }
                            } else {
                                if(this.shouldPushInArray(array[i][k], filter[k])) {
                                    newArray.Push(array[i]);
                                }
                                notAllKeysUndefined = true;
                            }
                        }
                    }
                }
            }
            if(notAllKeysUndefined) {
                return newArray;
            }
        }

        return array;
    }

    private shouldPushInArray(item, filter) {
        if(typeof filter !== 'string') {
            item = item.toString();
            filter = filter.toString();
        }

        // Filter main logic
        item = item.toLowerCase();
        filter = filter.toLowerCase();
        if(item.indexOf(filter) !== -1) {
            return true;
        }
        return false;
    }
}
0
Andris