Угловой 4-х трубный фильтр
Я пытаюсь использовать пользовательский канал для фильтрации моего *ngFor
цикл с использованием поля ввода с ngModel. С моим другим нестандартным каналом (sortBy) он работает отлично. Тем не менее, канал фильтра, кажется, делает это, что ни один из данных не появляется. Я все еще изучаю это, и я попробовал несколько вариантов безрезультатно:
-filter: term
-filter: {{term}}
-filter: 'term'
-filter" {{'term'}}
Поэтому я думаю, что проблема может лежать в другом месте кода. Если кто-то может помочь, я действительно ценю это.
Вот мой код:
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>
ТРУБЫ
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);
}
}
модуль
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 КОМПОНЕНТ
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";
}
3 ответа
Вот рабочий планкр с фильтром и трубой. https://plnkr.co/edit/vRvnNUULmBpkbLUYk4uw?p=preview
Как отметил в комментарии developer033, вы передаете одно значение в канал фильтра, когда канал фильтра ожидает массив значений. Я бы сказал трубе ожидать единственное значение вместо массива
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);
}
}
Я бы согласился с DeborahK, что из соображений производительности следует избегать нечистых труб. В состав plunkr входят журналы консоли, где вы можете увидеть, как называется нечистая труба.
Подпись метода преобразования изменилась где-то в RC Angular 2. Попробуйте что-то вроде этого:
export class FilterPipe implements PipeTransform {
transform(items: any[], filterBy: string): any {
return items.filter(item => item.id.indexOf(filterBy) !== -1);
}
}
И если вы хотите обработать пустые значения и сделать регистр фильтра нечувствительным, вы можете сделать что-то более похожее на то, что у меня здесь:
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;
}
}
И ПРИМЕЧАНИЕ: сортировка и фильтрация в трубах - это большая проблема с производительностью, и они НЕ рекомендуются. См. Документы здесь для получения дополнительной информации: https://angular.io/guide/pipes
Трубы в Angular 2+ - это отличный способ для преобразования и форматирования данных прямо из ваших шаблонов.
Трубы позволяют нам изменять данные внутри шаблона; то есть фильтрация, упорядочение, форматирование дат, чисел, валют и т. д. Быстрый пример: вы можете перенести строку в нижний регистр, применив простой фильтр в коде шаблона.
Список встроенных каналов из примеров списка API
{{ user.name | uppercase }}
Пример угловой версии 4.4.7. ng version
Пользовательские трубы, которые принимают несколько аргументов.
HTML « *ngFor="let student of students | jsonFilterBy:[searchText, 'name'] "
TS « transform(json: any[], args: any[]) : any[] { ... }
Фильтрация содержимого с использованием трубы " 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;
}
}
добавить в @NgModule
" Добавлять JsonFilterByPipe
в ваш список объявлений в вашем модуле; если вы забудете это сделать, вы получите сообщение об ошибке jsonFilterBy
, Если вы добавите в модуль, то он будет доступен для всех компонентов этого модуля.
@NgModule({
imports: [
CommonModule,
RouterModule,
FormsModule, ReactiveFormsModule,
],
providers: [ StudentDetailsService ],
declarations: [
UsersComponent, UserComponent,
JsonFilterByPipe,
],
exports : [UsersComponent, UserComponent]
})
export class UsersModule {
// ...
}
Имя файла: users.component.ts
а также StudentDetailsService
создан по этой ссылке.
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;
}
}
Имя файла: 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>
Я знаю, что это устарело, но думаю, что у меня есть хорошее решение. По сравнению с другими ответами, а также с принятым, мой принимает несколько значений. В основном фильтруйте объект с параметрами поиска ключ: значение (также объект внутри объекта). Также он работает с числами и т. Д., Потому что при сравнении он преобразует их в строку.
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;
}
}