角度で検索フィルタを作成する


UI上のユーザーに表示されるデータの長いリストがあるシナリオを考えてみましょう.これは、ユーザーが任意の検索機能を提供せずに、この長いリスト内の任意の特定のキーワードを検索する面倒です.したがって、我々のユーザーの生活を容易にするために、我々は通常、私たちのUI上で検索フィルタを実装します.
だから今、問題は、それを実装する方法ですか?しかし、それは非常に簡単です😉 我々が望むすべては、配列として配列をとって、我々が供給する期間に基づいてその配列の部分集合を返すフィルタです.角度で、データを他の形式に変換するこの方法はPipes . 最初にもう少し理解しましょうpipes 実装を開始する前に.

角のパイプ


パイプはデータを入力として取り込み、所望の出力に変換する.パイプはHTMLテンプレート式とコンポーネントの両方で使用できます.アングルは、Currencypipe、DatePipe、DecimalPipeなどのいくつかの組み込みパイプを提供します.以下のコードをチェックして、次のアクションのスニペットをチェックします.
dateObj = Date.now();

// HTML template expression syntax using pipe operator (|)
{{ dateObj | date }}               // output is 'Jun 15, 2015'
{{ dateObj | date:'medium' }}      // output is 'Jun 15, 2015, 9:43:11 PM'
{{ dateObj | date:'shortTime' }}   // output is '9:43 PM'
{{ dateObj | date:'mm:ss' }}       // output is '43:11'

// Using in component
constructor(private datePipe: DatePipe) { 
    console.log(datePipe.transform(Date.now(),'yyyy-MM-dd'));
    //2019-07-22
}
パイプは2種類の-純粋で汚れている.アングルパイプの詳細についてはvisit this link .

検索フィルタの実装


フィルターパイプを作る


パイプにフィルタのコードを入れましょう.このコードをコピー&ペーストしますfilter.pipe.ts :
// filter.pipe.ts

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

@Pipe({ name: 'appFilter' })
export class FilterPipe implements PipeTransform {
  /**
   * Pipe filters the list of elements based on the search text provided
   *
   * @param items list of elements to search in
   * @param searchText search string
   * @returns list of elements filtered by search text or []
   */
  transform(items: any[], searchText: string): any[] {
    if (!items) {
      return [];
    }
    if (!searchText) {
      return items;
    }
    searchText = searchText.toLocaleLowerCase();

    return items.filter(it => {
      return it.toLocaleLowerCase().includes(searchText);
    });
  }
}
このパイプ定義は以下のキーポイントを明らかにします.
  • パイプはパイプのメタデータで装飾されたクラスです.
  • PortTransformインターフェイスのTransformメソッドを実装し、入力値を受け取り、オプションのパラメーターを受け取り、変換された値を返します.我々のフィルタパイプでは、2つの入力arraysearch text をフィルタリングする.
  • これがパイプであることを角度で言うために@Pipe decorator , コア角ライブラリからのインポート.
  • @ pipeデコレータでは、テンプレート式内で使用するパイプ名を定義できます.それは有効なJavaScript識別子でなければなりません.私たちのパイプの名前はappFilter .
  • パイプの使用


    パイプを使用するには、まず、アプリケーションモジュールにインポートする必要があります.我々app.module.ts ファイルは次のようになります.
    // app.module.ts
    
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    
    import { AppComponent } from './app.component';
    
    import { FilterPipe } from './pipes/filter.pipe'; // -> imported filter pipe
    
    @NgModule({
      declarations: [
        AppComponent,
        FilterPipe // -> added filter pipe to use it inside the component
      ],
      imports: [
        BrowserModule,
        FormsModule
      ],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    
    今、我々はフィルタパイプを使用することができますApp Component . それを仮定しましょうapp.component.html 我々は、我々が我々の入ることができる入力箱を持っていますsearchText そして、これを利用するリストpipe 結果をフィルタリングする.
    <!-- app.component.html -->
    
    <div class="content" role="main">
      <div class="card">
        <div class="form-group">
          <label for="search-text">Search Text</label>
          <input type="email" class="form-control" id="search-text" aria-describedby="search-text" 
            [(ngModel)]="searchText" placeholder="Enter text to search" 
            autofocus>
        </div>
        <ul class="list-group list-group-flush">
          <!-- results of ngFor is passed to appFilter with argument searchText -->
          <li class="list-group-item" *ngFor="let c of characters | appFilter: searchText">
            {{c}}
          </li>
        </ul>
      </div>
    </div>
    
    // app.component.ts
    
    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss']
    })
    export class AppComponent {
      title = 'angular-text-search-highlight';
      searchText = '';
      characters = [
        'Ant-Man',
        'Aquaman',
        'Asterix',
        'The Atom',
        'The Avengers',
        'Batgirl',
        'Batman',
        'Batwoman',
        ...
      ]
    }
    
    それだ!我々のアプリケーションを実行すると、次の出力が表示されます.
    でもねえ!我々の検索結果は、最初に示されたように強調されていません😟
    理由はPipes 角度で、それに渡されるデータだけは、望ましい出力に変わります.それはそれに関連するHTMLを操作しません.検索結果を強調するには、HTMLを操作する必要がありますsearchText その一部.これはDirectives .

    角度の指示


    角ディレクティブは、新しい構文を与えることでHTMLのパワーを拡張するために使用されます.ディレクティブの3種類があります.
  • コンポーネント-テンプレートを持つディレクティブ.
  • 構造ディレクティブ- DOM要素の追加と削除によってDOMレイアウトを変更します.
  • 属性ディレクティブ-要素、コンポーネント、または別のディレクティブの外観や振る舞いを変更します.
  • この文書の範囲外です.角度ディレクティブについてもっと知りたい場合はvisit this link .

    アプリケーションのディレクティブの実装


    我々のケースでは、我々はattribute directive 強調表示するsearchText 結果の一覧で.

    ハイライトディレクティブの作成


    属性ディレクティブは、@ directiveで注釈付きのコントローラクラスを構築することを最小限にする必要があります.コントローラクラスは、望ましいディレクティブ動作を実装します.
    強調表示のコードでディレクティブを設定しましょう.このコードをコピー&ペーストしますhighlight.pipe.ts :
    // highlight.directive.ts
    
    import { Directive, Input, SimpleChanges, Renderer2, ElementRef, OnChanges } from '@angular/core';
    
    @Directive({
      selector: '[appHighlight]'
    })
    export class HighlightDirective implements OnChanges {
      @Input() searchedWord: string; // searchText
      @Input() content: string; // HTML content
      @Input() classToApply: string; //class to apply for highlighting
      @Input() setTitle = false; //sets title attribute of HTML
    
      constructor(private el: ElementRef, private renderer: Renderer2) { }
    
      ngOnChanges(changes: SimpleChanges): void {
        if (!this.content) {
          return;
        }
    
        if (this.setTitle) {
          this.renderer.setProperty(
            this.el.nativeElement,
            'title',
            this.content
          );
        }
    
        if (!this.searchedWord || !this.searchedWord.length || !this.classToApply) {
          this.renderer.setProperty(this.el.nativeElement, 'innerHTML', this.content);
          return;
        }
    
        this.renderer.setProperty(
          this.el.nativeElement,
          'innerHTML',
          this.getFormattedText()
        );
      }
    
      getFormattedText() {
        const re = new RegExp(`(${this.searchedWord})`, 'gi');
        return this.content.replace(re, `<span class="${this.classToApply}">$1</span>`);
      }
    }
    

    The logic is to manipulate the current HTML element by adding <span> tag in between the searchText and applying the highlighting class to it.


    2 .ディレクティブの使用


    パイプを使用するには、まず、アプリケーションモジュールにインポートする必要があります.我々app.module.ts ファイルは次のようになります.
    // app.module.ts
    
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    
    import { AppComponent } from './app.component';
    
    import { HighlightDirective } from './directives/highlight.directive'; // ->  imported directive
    import { FilterPipe } from './pipes/filter.pipe';
    
    @NgModule({
      declarations: [
        AppComponent,
        HighlightDirective, // -> added directive
        FilterPipe
      ],
      imports: [
        BrowserModule,
        FormsModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    
    このディレクティブをHTMLファイルで使用するには、通常のHTML属性として追加します.次のようになります.
    <!-- app.component.html -->
    
    <div class="content" role="main">
      <div class="card">
        <div class="form-group">
          <label for="search-text">Search Text</label>
          <input type="email" class="form-control" id="search-text" aria-describedby="search-text" 
            [(ngModel)]="searchText" placeholder="Enter text to search" 
            autofocus>
        </div>
        <ul class="list-group list-group-flush">
          <li class="list-group-item" *ngFor="let c of characters | appFilter: searchText"
            appHighlight [searchedWord]="searchText" [content]="c"  
            [classToApply]="'font-weight-bold'" [setTitle]="'true'">
            {{c}}
          </li>
        </ul>
      </div>
    </div>
    
    今、我々は希望の出力を見ることができるだろう!😌
    あなたは私のチェックアウトGitHub repo このポストの完全な実装のために.
    yaを参照してください!私の次のポストまで😋