HTTPサービスでリモートのデータを加えたり除いたりする」で、HTTPサービスによりリモートのデータを編集したり、追加・削除もできるようにしました。フィールドに入力したテキストから、データが検索できるようにコンポーネントを加えます。5入門」シリーズは今回が最後です。サービスに検索のメソッドを加えるまず、サービスモジュール(heroine.service)にデータ検索のメソッド(searchHeroines())をつぎのように加えます。引数(term)は検索語の文字列です。テキストが空白でないことを確かめたうえで、HttpClient.get()メソッドに引数としてURL(url)を渡します。この処理の組み立ては、データを取り出すメソッド(getHeroines())とよく似ています(後掲コード001参照)。異なるのは、URLにクエリ文字列を加えていることです。この文字列をもとにリモートデータが検索されます。検索語が空白だった場合の戻り値は、空のObservableオブジェクトです。[])));}}サービスモジュール(heroine.service)のTypeScriptコード(HeroineServiceクラス)はこれででき上がりですので、つぎのコード001にまとめます。componentコマンドで、アプリケーションのディレクトリ(angular-tour-of-heroines)につぎのように検索のコンポーネントをつくります。heroine-search検索コンポーネント(heroine-search.component)のTypeScptコードから定めます。このクラス(HeroineSearchComponent)は、書いている途中で動きを試して確かめるのはむずかしいので、コード002にでき上がりを示してしまいましょう。アプリケーションのモジュール(app.module)にはngコマンドで検索コンポーネントが加えられました。こちらもこれ以上手は加えませんので併せて掲げます。{}検索のコンポーネント(heroine-search.component)のTypeScriptコードは、つぎのようにObservableのほかにSubjectクラスをimportしました。SubjectはObservableのサブクラスです。そのインスタンスをprivateのプロパティ(searchTerms)に与えたうえで、コンポーネントがつくられたとき(ngOnInit()メソッド)Observableで型づけされたプロパティ(heroines$)に納めています(識別子の終わりの$はObservableを表すために添えます)。SubjectクラスがObservableと違うのは、データをあとから加えられることです(「AngularのRxJSを使ってデータの受け渡しをする」の「任意のタイミングでデータを流すSubject」参照)。すると、ユーザーがテキストフィールドに検索語を入力したとき、サービスに渡して検索することができるのです。Subjects」の「Subject」参照)。Observer.next()はオブジェクトにあとからデータを加えるメソッドです。ユーザーが検索語を入力したときに呼び出すメソッド(search()は、引数(term)に渡されたその文字列をObserver.next()でオブジェクトに差し込みます。そのデータを処理するためにRxJSから3つのメソッド(オペレータ)をimportしました。ngOnInit()メソッドでSubjectインスタンス(searchTerms)をObservableのプロパティ(heroines$)に納めたあと、Observable.pipe()メソッドで3つつづけて呼び出しています。検索のメソッド(search()は、テキストフィールドでキー入力されるたびに呼び出されることになります。それをそのままデータサーバーに送ったら、負荷が膨らみ過ぎてしまうでしょう。入力されたデータの出力を、引数のミリ秒待たせるのがdebounceTime()です。指定時間が過ぎたとき、直近の値だけをObservableオブジェクトで返します。同じ検索語をつづけざまに問い合わせるのも無駄です。distinctUntilChanged()は、同じ項目がつづいたときはそのデータを省いて出力する新たなObservableオブジェクトにします。そのうえで、出力された検索語(term)をサービスのメソッド(searchHeroines())に送るのが、switchMap()です。this.heroineService.searchHeroines(term)),);}}debounceTime()が負荷を下げ、distinctUntilChanged()で無駄を減らしました。それでも、検索結果が返る前につぎの検索語を送ってしまうことはありえます。それでも、switchMap()は新たなObservableを送るとき、前のオブジェクトは破棄してくれるのです。HTTPリクエストそのものは取り消されません。Observableクラスのメソッド(オペーレータ)とオブジェクトの扱いに用いられる関数を、前にご説明したものも含めてつぎの表001にまとめます。参照するObservableオブジェクトから、引数の時間が過ぎたのちに値をひとつ出力する。複数の値が渡された場合は、直近の値のみ出力される。参照するObservableの出力するすべての項目から、同じ項目の連続した重複は除いて出力する新たなObservableオブジェクトを返す。引数(compare)の比較関数が与えられると連続する項目をふたつの引数に受け取って同じかどうか比べ、引数がなければ等価比較される。引数値が出力される新たなObservableオブジェクトをメソッドの実行時ただちにつくり、あとでそのオブジェクトが完了を知らせる。引数のオペーレータの処理をつなぎあわせて順に行う。Observableオブジェクトを実行して、引数に登録したObserverまたは関数により出力の通知を扱う。参照するObservableオブジェクトの値に引数(project)の関数に渡してObservableに変え、出力するObservableインスタンスに組み入れる。新たな値からつくられたObservableは、前のオブジェクトを破棄して出力インスタンスに差し込まれる。Observableオブジェクトのエラーをキャッチして、新たなObservableオブジェクトを返すか、エラーをスローする。Observableオブジェクトの出力すべてに引数の副次的な処理を行い、もとのObservableオブジェクトそのものを返す。検索コンポーネントのテンプレートをつくる検索コンポーネント(heroine-search.component)のテンプレートはさほど行数もありません。でき上がりをコード003に示しましょう。スタイルを定めるCSSファイルも併せて掲げます。テキストフィールド(<input>要素)に入力したキーを放すイベント(keyup)に、コンポーネントの検索メソッド(search())がバインディングされて呼び出されます。引数は変数(searchBox)で参照した要素の入力値(valueプロパティ)です。検索して得られたデータはプロパティ(heroines$)に納められますので、*ngForディレクティブでひとつずつ取り出してリストに加え、詳細情報へのリンク(routerLinkディレクティブ)も与えられています。asyncの記述でしょう。これはAsyncPipeと呼ばれます。プロパティに納められているのはObservableオブジェクトです(わかるように$をつけました)。このままでは値が得られません。TypeScriptコードであれば、Observable.subscribe()メソッドを呼び出さなければならないところです。ダッシュボードに検索コンポーネントを加える検索コンポーネント(heroine-search.component)の要素(セレクタapp-heroine-search)は、以下のようにダッシュボードコンポーネント(dashboard.component)のテンプレートの最後に加えてください。これでダッシュボードに検索フィールドが加わり、テキストを打ち込めばその文字列を含むデータがリストで表れます(図001)。項目をクリックすれば、そのデータの詳細情報画面に移るはずです。grid-pad"></div><app-heroine-search></app-heroine-search>図001■検索フィールドにテキストを入力すると該当するデータがリストで表れるダッシュボードコンポーネントのテンプレートは、つぎのコード004のとおりです。10」でお確かめください。