Пользовательская труба Angular 4 Filter Search

Итак, я пытаюсь создать собственный канал для поиска нескольких значений в цикле ngFor. Я искал несколько часов для хорошего рабочего примера, и большинство из них основаны на предыдущих сборках и, похоже, не работают. Итак, я построил Pipe и использовал консоль, чтобы передать мне значения. Однако я не могу отобразить вводимый текст.

Вот предыдущие места, где я искал рабочие примеры:

Угловой 4-трубный фильтр

http://jilles.me/ng-filter-in-angular2-pipes/ < / а>

https://mytechnetknowhows.wordpress.com/2017/02/18/angular-2-pipes-passing-multiple-filters-to-pipes/

https://plnkr.co/edit/vRvnNUULmBpkbLUYk4uw?p=preview

https://www.youtube.com/results?search_query=filter+search+angular+2

https://www.youtube.com/watch?v=UgMhQpkjCFg

Вот код, который у меня сейчас есть:

component.html

<input type="text" class="form-control" placeholder="Search" ngModel="query" id="listSearch" #LockFilter>

      <div class="panel panel-default col-xs-12 col-sm-11" *ngFor="let lock of locked | LockFilter: query">
        <input type="checkbox" ngModel="lock.checked" (change)="openModal($event, lock)" class="check" id="{{lock.ID}}">
        <label for="{{lock.ID}}" class="check-label"></label>
        <h3 class="card-text name" ngModel="lock.name">{{lock.User}}</h3>
        <h3 class="card-text auth" ngModel="lock.auth">{{lock.AuthID}}</h3>
        <h3 class="card-text form" ngModel="lock.form">{{lock.FormName}}</h3>
        <h3 class="card-text win" ngModel="lock.win">{{lock.WinHandle}}</h3>
      </div>

pipe.ts

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

@Pipe({
  name: 'LockFilter'
})

export class LockFilterPipe implements PipeTransform {
  transform(locked: any, query: string): any {
    console.log(locked); //this shows in the console
    console.log(query); //this does not show anything in the console when typing
    if(!query) {
      return locked;
    }
    return locked.filter((lock) => {
      return lock.User.toLowerCase().match(query.toLowerCase());
    });
  }
}

Я импортировал трубу в модуль.

Я все еще новичок в Angular 4 и пытаюсь понять, как это работает. В любом случае спасибо за вашу помощь!

Думаю, мне нужно будет более конкретным. Я уже построил поиск с фильтром в JS, который не фильтрует все параметры, что я и пытаюсь сделать. Не просто фильтровать имя пользователя. Я фильтрую все 4 части данных. Я выбрал Pipe, потому что это то, что предлагает вам сделать Angular, как они изначально использовали их в AngularJS. Я просто пытаюсь по сути воссоздать фильтрующий канал, который у нас был в AngularJS, который они удалили для повышения производительности. Все варианты, которые я нашел, не работают или взяты из предыдущих сборок Angular.

Если вам понадобится что-нибудь еще из моего кода, дайте мне знать.


person T. Evans    schedule 17.10.2017    source источник
comment
Каналы, реализующие бизнес-логику, отличную от форматирования вывода, в Angular в значительной степени рассматриваются как антипаттерны. Вместо этого используйте функции для инкапсуляции логики. Затем используйте его в своей привязке: let lock of filteredLocks ()   -  person Igor Soloydenko    schedule 17.10.2017
comment
У меня есть пример: stackoverflow .com / questions / 45199776 /   -  person DeborahK    schedule 17.10.2017
comment
Ага! Ответ Деборы - это путь   -  person Igor Soloydenko    schedule 17.10.2017
comment
@DeborahK Я просмотрел ваш пример по ссылке. Я не мог заставить это работать. Я пытаюсь отфильтровать все параметры, а не только имя пользователя. Почему бы вам не использовать Pipe, как предлагает Angular? Я уже создал фильтр поиска, используя JS в файле component.ts, но он не хочет фильтровать все параметры, поэтому я решил попробовать Pipe.   -  person T. Evans    schedule 17.10.2017
comment
Я обсуждаю это здесь: blogs.msmvps.com/deborahk/filtering-in-angular Он включает информацию о том, почему каналы не рекомендуются для сортировки и фильтрации и как делать несколько значений.   -  person DeborahK    schedule 17.10.2017
comment
@ T.Evans, что касается вашего комментария о том, что Angular рекомендует использовать pipe в этом сценарии, на самом деле не соответствует действительности;) angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe   -  person AJT82    schedule 21.10.2017


Ответы (6)


Мне нужно реализовать функцию поиска в моем локальном, и здесь обновлен ваш код. пожалуйста, сделай так.

Вот код, который мне нужно обновить.

Структура каталога

app/
   _pipe/
        search/
          search.pipe.ts
          search.pipe.spec.ts
app/ 
   app.component.css
   app.component.html
   app.component.ts
   app.module.ts
   app.component.spec.ts

запуск команды для создания трубы

ng g pipe search

component.html

<input type="text" class="form-control" placeholder="Search" [(ngModel)]="query" id="listSearch">
    <div class="panel panel-default col-xs-12 col-sm-11" *ngFor="let lock of locked | LockFilter: query">
    <input type="checkbox" (change)="openModal($event, lock)" class="check" id="{{lock.ID}}">
    <label [for]="lock.ID" class="check-label"></label>
    <h3 class="card-text name">{{lock.User}}</h3>
    <h3 class="card-text auth">{{lock.AuthID}}</h3>
    <h3 class="card-text form">{{lock.FormName}}</h3>
    <h3 class="card-text win">{{lock.WinHandle}}</h3>
</div>

component.js

Примечание. В этом файле я должен использовать фиктивные записи для целей реализации и тестирования.

import { Component, OnInit } from '@angular/core';
import { FormsModule }   from '@angular/forms';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
    export class AppComponent implements OnInit{
    public search:any = '';
    locked: any[] = [];

    constructor(){}

    ngOnInit(){
        this.locked = [
            {ID: 1, User: 'Agustin', AuthID: '68114', FormName: 'Fellman', WinHandle: 'Oak Way'},
            {ID: 2, User: 'Alden', AuthID: '98101', FormName: 'Raccoon Run', WinHandle: 'Newsome'},
            {ID: 3, User: 'Ramon', AuthID: '28586', FormName: 'Yorkshire Circle', WinHandle: 'Dennis'},
            {ID: 4, User: 'Elbert', AuthID: '91775', FormName: 'Lee', WinHandle: 'Middleville Road'},
        ]
    }
}

module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule }   from '@angular/forms';
import { AppComponent } from './app.component';
import { SearchPipe } from './_pipe/search/search.pipe';


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

pipe.ts

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

@Pipe({
    name: 'LockFilter'
})

export class SearchPipe implements PipeTransform {
    transform(value: any, args?: any): any {

        if(!value)return null;
        if(!args)return value;

        args = args.toLowerCase();

        return value.filter(function(item){
            return JSON.stringify(item).toLowerCase().includes(args);
        });
    }
}

Я надеюсь, что вы получаете функциональность канала, и это вам поможет.

person Chintan Kotadiya    schedule 10.12.2017

Простой filterPipe для Angular 2+

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

@Pipe({
  name: 'filter'
})
export class filterPipe implements PipeTransform {

  transform(items: any[], field:string, value: string): any[] {

    if(!items) return [];
    if(!value) return items;


    return items.filter( str => {
          return str[field].toLowerCase().includes(value.toLowerCase());
        });
   }
}

Вот HTML

<input type="text" class="form-control" placeholder="Search" id="listSearch" #search>
    <div class="panel panel-default col-xs-12 col-sm-11" *ngFor="let lock of locked | filter:'propName': search.value>
    <input type="checkbox" (change)="openModal($event, lock)" class="check" id="{{lock.ID}}">
    <label [for]="lock.ID" class="check-label"></label>
    <h3 class="card-text name">{{lock.User}}</h3>
    <h3 class="card-text auth">{{lock.AuthID}}</h3>
    <h3 class="card-text form">{{lock.FormName}}</h3>
    <h3 class="card-text win">{{lock.WinHandle}}</h3>
</div>

в HTML PropName - фиктивный текст. Вместо PropName используйте любой ключ свойства объекта.

person Virendra Pandey    schedule 29.08.2018

Следуйте этому коду, чтобы отфильтровать определенный столбец вместо всех столбцов в таблице с помощью настраиваемых фильтров.

filename.component.html

<table class="table table-striped">
  <thead>
    <tr>
      <th scope="col">product name </th>
      <th scope="col">product price</th>
   </tr>
  </thead>

  <tbody>
    <tr *ngFor="let respObj of data | filter:searchText">
      <td>{{respObj.product_name}}</td>
      <td>{{respObj.product_price}}</td>
    </tr>
 </tbody>
</table>

filename.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';


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

export class ProductlistComponent implements OnInit  {

  searchText: string;

  constructor(private http: HttpClient) { }
  data: any;
  ngOnInit() {
    this.http.get(url)
      .subscribe(
        resp => {
         this.data = resp;

        }
      )
  }
}

filename.pipe.ts
Создайте класс и реализуйте его с помощью PipeTransform, чтобы мы могли написать собственный фильтр с помощью метода transform.

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'filter'
})
export class PipeList implements PipeTransform {
  transform(value: any, args?: any): any {
    if(!args)
     return value;
    return value.filter(
      item => item.product_name.toLowerCase().indexOf(args.toLowerCase()) > -1
   );
  }
}
person Madhavi Gandu    schedule 18.12.2019

Вот простое объяснение создания пользовательского канала… поскольку доступные каналы его не поддерживают. Я нашел это решение здесь .. красиво объяснил это

Создайте файл трубы advanced-filter.pipe

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

@Pipe({
  name: 'advancedFilters'
})

export class AdvancedFilterPipe implements PipeTransform {

  transform(array: any[], ...args): any {
    if (array == null) {
      return null;
    }

    return array.filter(function(obj) {
      if (args[1]) {
        return obj.status === args[0];
      }
      return array;
    });

  }

}

Здесь array - это будет массив данных, переданный в ваш пользовательский канал obj - будет объектом данных, используя этот объект, вы можете добавить условие для фильтрации данных

Мы добавили условие obj.status === args[0], чтобы данные получали фильтр по статусу, который передается в файле .html.

Теперь импортируйте и объявите пользовательский канал в файле module.ts компонента:

import {AdvancedFilterPipe} from './basic-filter.pipe';

//Declare pipe

@NgModule({

    imports: [DataTableModule, HttpModule, CommonModule, FormsModule, ChartModule, RouterModule],

    declarations: [ DashboardComponent, AdvancedFilterPipe],

    exports: [ DashboardComponent ],

    providers: [{provide: HighchartsStatic}]

})

Использование созданной пользовательской угловой трубы в файле .html

<table class="table table-bordered" [mfData]="data | advancedFilters: status" #mf="mfDataTable" [mfRowsOnPage]="rowsOnPage" [(mfSortBy)]="sortBy" [(mfSortOrder)]="sortOrder">

                <thead>
                       <tr>
                             <th class="sortable-column" width="12%">
                                 <mfDefaultSorter by="inquiry_originator">Origin</mfDefaultSorter>
                             </th>
                        </tr>
                </thead>

                <tbody class="dashboard-grid">

                                <ng-container *ngFor="let item of mf.data; let counter = index;">

                                                <tr class="data-row {{ item.status }} grid-panel-class-{{ counter }}">                                      

                                                                <td class="align-center">{{ item.trn_date }}</td>

                                                                <td>{{ item.trn_ref }}</td>

                                                </tr>

                </tbody>

</table>


//If you are using *ngFor and want to use custom angular pipe then below is code

<li *ngFor="let num of (numbers | advancedFilters: status">
  {{ num | ordinal }}
</li>
person Prashant M Bhavsar    schedule 17.12.2018

Вот простая Java-подобная логика, которая может показаться не очень компактной с точки зрения машинописного текста:

transform(value:IBook[], keyword:string) {       
        if(!keyword)
        return value;
        let filteredValues:any=[];      
        for(let i=0;i<value.length;i++){
            if(value[i].name.toLowerCase().includes(keyword.toLowerCase())){
                filteredValues.push(value[i]);
            }
        }
        return filteredValues;
    }
<h2>Available Books</h2>
<input type="text" [(ngModel)]="bookName"/>
<ul class="books">
  <li *ngFor="let book of books | search:bookName"
    [class.selected]="book === selectedBook"
    (click)="onSelect(book)">
    <span class="badge">{{book.name}}</span>
  </li>
</ul>

person Sen    schedule 20.03.2019

Вы можете использовать данную функцию вместо события (input) вашего поля ввода

filterNames(event)
{
 this.names_list = this.names_list.filter(function(tag) {
 return tag.name.toLowerCase().indexOf(event.target.value.toLowerCase()) >= 0;
 });
}

Надеюсь, это поможет..

person Rahul Gupta    schedule 17.10.2017