[ Vue.js ] b-table の行選択を可能にし、 選択した行 データ を取得する サンプル コード

BootstrapVue の b-table を用いて特定の行を選択し、選択した行データの内容を取得し、画面に表示する サンプル コード を説明します。 使用する データ 出発地点は、以下の コード とします。 この状態では、表の行を クリック しても選択された状態にはなりませんので、行を選択可能な状態にしていきます。 行を選択可能に select-mode プロパティ ここでは、 select-mode prop を活用します。 select-mode プロパティには以下の3つの値が指定できます。今回は single を使っていきます。 multi: クリック の度に選択、解除。(デフォルト) single: 1 行のみ選択可能 range: shift + クリック や Ctrl (Cmd) + クリック で複数行の選択も可能になる selectable プロパティ select-mode プロパティを使うためには、 兎にも角にも行を選択可能にしなければいけません。行を選択可能にするためには selectable プロパティ を使います。 これで以下のとおり、 デフォルト 動作である multi の動作になります。 試しに shift + クリック をしても、 複数行 は選択できません。 select-mode=”single” 次に、 select-mode に single を指定します。 同時に 1 行しか選択できないように、振る舞いが変化しました。 ‘single’ not defined 当初、 ‘select-mode’ に ‘singel’ や ‘multi’ を指定しても、 ‘single’ is not defined というエラーが出ていました。 以下のサイトを参考に、 primary-key を追加してみたら、 エラー が消え、その後、 primary-key を削除しても意図通り動作するようになりました。 詳細は調査しきれてないですが、 もし同様のエラーが出たら参考にしていただければと思います。 選択行の情報を取得 row-selected イベント それでは、選択した 1 行の データ を取得していきます。 まずは、いまの状態での Vue の振る舞いを Chrome の Dev Tools … Read more

[Vue.js]ドロップダウン(b-form-select)の表示内容を動的にフィルタリングしつつ、同時にテーブル(b-table)のアイテムをフィルタリングする方法

以前投稿した、「BootstrapVueのテーブル(b-table)で複数条件によるフィルタを実装する方法」では、複数の条件に従ってテーブルアイテムの内容がフィルタリングされるようにしましたが、今回は、条件として複数のドロップダウン(b-form-select)を使うだけでなく、1つ目のドロップダウンの内容に応じて2つ目のドロップダウンの内容を動的にフィルタリングしながら、同時にテーブルアイテムをフィルタリングする方法を説明します。 使うデータと基本のテーブル 今回は、2019年から2022年までに開催された、もしくはされる予定のサッカーの国際大会決勝をドロップダウンで年、月を絞り込みながら表示アイテムを絞り込んでいく、というシナリオを考えます。使用するデータは以下の通りです。 ドロップダウン(b-form-select)の設置 まずは、絞り込み用のドロップダウンを設置していきます。今回は、年、月の2つのドロップダウンを設置していきます。 データプロパティには、ドロップダウンで選択した値を保持するyearと、ドロップダウンに表示するリストを保持するyear_listを用意します。月も同様です。 ドロップダウンに表示するリストを作成します。 年、月共にリストに値が入りましたが、重複データもありますし、ソートもされていませんので、重複を排除し、ソートすることにします。 重複排除、ソート 重複の排除には以下のようなアロー関数を使うことにします。 重複が排除され、ドロップダウンがすっきりしました。次に、ソートをすることにします。 これで、検索用のドロップダウンの設置が完了しました。この状態では、ドロップダウンを選択しても特に何もおこりません。次に、本題である、ドロップダウンの内容を動的にフィルタリングするようにしてみます。 年(Year)の内容で、月(Month)のリスト項目を絞り込み ここでは、例えばYearドロップダウンで2021を選択した際に、Monthドロップダウンとして、1, 2, 7のみが表示されるように、Year, Monthの順でNarrow Downするようにしてみます。今回はwatchプロパティを使う方法で実装してみます。 ドロップダウンの値が変更されると、このfunctionが呼び出され、選択した値がnewValとして連携されますので、まずはmonthドロップダウンのリストに表示するプロパティのmonth_listを初期化し、データの中から選択されたyearのものだけをmonth_listに格納し、monthドロップダウンに表示するようにしています。このコードを追加すると、以下のような振る舞いになります。 これで、1つ目のドロップダウンの値に2つ目のドロップダウンの値が連動し、動的にドロップダウンの表示項目が変化するようになりました。最後に、この2つのドロップダウンの値に、テーブルアイテムを連動させてみます。 テーブル(b-table)をドロップダウン(b-form-select)の内容でフィルタリング 以下の投稿で説明した方法を、ほぼそのまま流用することで、ドロップダウンの値とテーブルを連動させてみます。細かい部分は、以下の投稿を参考にしてみてください。 上記を実装した結果は以下の通りです。テーブルアイテムが絞り込めて表示できていることが分かると思います。 まとめ 2022年を選択した際に一度テーブルが消えてしまう、一度値を選択すると全検索(当該項目でのフィルタリングなし)ができない、など実用上はもう少しブラッシュアップが必要かと思いますが、冗長になってしまうので、今回はここまでとします。 最終型のソースコード 余談ですが、wikipediaを参考に今回のサンプルデータを作成しましたが、2020年のイベントが軒並み2021年に延期されていることを再認識せざるを得ませんでした…

[Vue.js]BootstrapVueのテーブル(b-table)で複数条件によるフィルタを実装する方法

BootstrapVueのテーブルコンポーネントの<b-table>を使うと、簡単にきれいなテーブルが作成できます。この作成したテーブルを条件によって絞り込んで表示しようと思います。b-tableには、Built-inでフィルタ機能が実装されており、これも簡単にテーブルデータをフィルタリングすることができるのですが、単純にこのフィルタ機能を使うだけでは、列を指定してのフィルタや、複数条件を絡めたフィルタリングを実現することができません。今回は、2つの条件を絡めたフィルタリングでデータを絞り込む方法を説明します。 参考;公式Docs:BootsatrapVue Filtering 使うデータと基本のテーブル 公式サイトにあるものと同じサンプルデータを使います。name, first_name, last_nameの3つの列からなる4つのレコードです。 起動時に、mounted()でデータをテーブル表示用のコンポーネントプロパティであるitemsに読み込んで表示するだけのコードです。 Built-inフィルタ(全列対象) 次に、Built-inフィルタについて説明します。Built-inフィルタは、b-tableのプロパティに検索用の文字列を指定するだけで有効になります。ここでは、入力用のb-form-inputを使って動的にテーブルの内容をフィルタリングしていきます。 数字”8″を入力すると、8を含む行のみが表示されます。今回のデータはAge列のみ数字が入っていますので、89, 38の2行が表示されます。文字列”l”や”m”を入力すると、それぞれの文字が含まれる行のみが表示されます。今回のデータはAge列以外に文字列が入っていますので、実施的にはAge列以外の2列を対象としてフィルタリングされます。 Built-inフィルタ(特定列対象) 上述の通り、ほんの2〜3行追記するだけでフィルタリングが実装できます。ただし、実際の使用場面を考えれば、絞り込みたい列を指定することも一般的かと思います。そこで、次に特定の列でフィルタリングをする方法を説明します。 特定の1列を対象にフィルタリング それでは、first_name列のみを対象にフィルタリングを実装してみます。これは、:filter-included-fieldsプロパティを1つ追加することで実現できます。 参考:Built in filtering options 先程と同じ条件を入力した結果は以下のとおりです。数字を入れると、結果がゼロ件になり、”l”, “m”も、先程はLast Nameの方で検索にひっかかっていたレコードが表示されなくなっていることがわかります。 特定の2列を対象にフィルタリング 次に、first_nameに、last_nameをフィルタリング対象として加える場合を説明します。これは、:filter-included-fieldsの配列パラメータにlast_nameを追加するだけで実現可能です。 これも、同じように、数字(8)、文字列(“l”, “m”)で見ていきます。Age列は引き続きフィルタリング対象外なので、数字を入れても何も表示されないところは変わっていませんが、文字列を入力すると、一番最初の全列対象のフィルタリングと同じ結果に変わってきているため、First Name, Last Nameの2列がフィルタリング対象になっていることがわかります。 なお、同じフィルタリングを:filter-ignored-fieldsを使って、以下の用に記載することもできます。上のコードと下のコードの振る舞いは同じになります。 Custom Filter ここまで、1つのフィルタリング条件を入力し、1つ、または複数列に対してフィルタリングする例をみてきました。これらのようなシンプルなフィルタリングはBuilt-inフィルタリングで簡単に実装できることがわかりました。ところが、複数条件を使ったフィルタリングなど、少し複雑なフィルタリングを実装しようとすると、Built-inフィルタリングでは実現することができません。そこで必要になるのが、Custom Filterです。 参考:Custom filter function Custom Filterの基本 まずは、Custom Filterを使って、Built-inフィルタリングと同等のフィルタリングを実装してみます。公式ドキュメントによると、Custom Filterは:filter-functionプロパティを使って、method内の関数を呼び出すことができ、その際に以下の2つの引数を渡す、ということです。 オリジナルアイテム行レコードデータオブジェクト(the original item row record data object) フィルタープロパティの内容(文字列、正規表現、配列、オブジェクト) 上記に従って、tableFilterというフィルタリング用の関数を作成し、それを:filter-functionで指定することにします。 単一条件でのフィルタ tableFilterでは、まず確認のために、何が渡されているかを出力しています。実質的な処理は最後の行のみで、検索用に入力した値が、テーブルの行単位で渡されるデータのなかに含まれていればtrueを、そうでなければfalseを返す、ということをしています。このコードで同じ用に数字の8を入力してみます。 出力したログを確認してみます。1行ずつ、tableFilterに引数rowとしてデータが渡されていることがわかります。また、検索用に入力した数字はstringとして扱われていますが、rowとして渡されたageのデータはnumberとなっていることがわかります。この値を比較する際は型を合わせるなどひと手間必要そうです。 次に、文字列”l”を入力してみます。2行目の”Larsen”がFirst Nameとして”l”を含んでいるため表示されてほしいところですが、表示されません。 出力したログをみてみます。filterpropとして渡されているのは小文字の”l”で、row.first_nameに含まれているのは大文字の”L”のため、不一致になっています。Built-inフィルタリングではこのあたり”よしな”に処理してくれていますので、Custom Filteringの場合は要注意ですね。 大文字小文字の区別なくフィルタリングするようにコードを修正します。(Cosole.log部分は削除しています) 修正後のフィルタリングは以下のようになります。無事小文字の”l”でも”Larsen”が表示されるようになりました。大文字”A”を入力しても、小文字の”a”を含むデータが表示されています。 複数列を対象としたフィルタ 次に、Built-inフィルタリングの:filter-included-fieldsと同様、フィルタリング対象列を複数にする場合をみていきます。先程同様、filterpropに渡された検索文字列が、rowで渡される各行のデータの、first_name, last_nameそれぞれに含まれているかをチェックし、いずれかに含まれていればtrueを返すようにtableFilterを変更します。 以下の用に、Age列にはフィルタリングが効いていないままである一方、”l”を入力することで、先程は表示されなかったLast Nameに”l/L”が含まれるデータが表示されるようになりました。 複数条件でのフィルタ ここまででCustom FilterでBuilt-inフィルタリング同等の機能を実装することができるようになりました。ここからがやっと本題となる、複数条件でのフィルタリングを実装していきます。ここでは、以下を実現しようとします。 年齢、名前の2つの検索条件を入力 年齢、名前共に、空欄であれば全件表示とする(空欄データがないため表示しない、ということにはしない) 年齢:入力された値がAge列に含む場合、表示する 名前:入力された値が、First Name列, またはLast Name列に含まれる場合、表示する 年齢と名前はAND条件とする(例:「年齢に”8″を含み、かつ名前に”g”を含む」=> 3行目、89歳 Geneva Wilsonを表示 最初に、複数条件を入力できるようにフォームを追加し、それぞれの値を保持するためのプロパティを用意します。 検索条件が2つ(age, name)になった状態です。v-modelのageもnameは何もフィルタリング機能と関連していないため、これらに入力しても何もフィルタリングされません。 ここで、ageまたはnameプロパティが変更されたことをトリガーにフィルタリングさせることを考えます。computedプロパティを使ってこれを実現してみます。先程まで使っていたデータプロパティのsearch_textの代わりに、computedプロパティのfilterを用意します。これは、単純にデータプロパティのage, nameを配列で返す、というものです。 次に、b-table側で:filterプロパティも同様にデータプロパティのsearch_textの代わりに、作成したcomputedプロパティのfilterを指定します。 これで準備完了といきたいところですが、このままだと以下のエラーが出てしまいます。原因は初回、age, nameのいずれかがnullの状態でtoLowerCaseを呼んでいるためです。このエラーへの対応と、要件通り、Ageも対象としたロジックをtableFilterに実装します。 今回は、前回使用した引数で渡されてくるpropfilterの値を使うのではなく、データプロパティの値との比較でロジックを組んでいます。実行結果は以下のとおりです。ageだけ、age+name, nameだけ、いずれでも期待した結果が表示されることがわかります。 まとめ 利用シーンはそれなりにありそうながら、中々わかりやすいサンプルが見つけられなかったため、自分自身の整理の意味も込めて投稿しました。BootstrapVueの公式ドキュメントにすべて記載があるといえばありますが、実例が乏しく苦労しましたが、一度わかってしまえばとても分かりやすい仕組みなので、何かの参考にしていただければ幸いです。 最終型のソースコード References