Vue.jsJapanese

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

Vue.js

以前投稿した、「BootstrapVueのテーブル(b-table)で複数条件によるフィルタを実装する方法」では、複数の条件に従ってテーブルアイテムの内容がフィルタリングされるようにしましたが、今回は、条件として複数のドロップダウン(b-form-select)を使うだけでなく、1つ目のドロップダウンの内容に応じて2つ目のドロップダウンの内容を動的にフィルタリングしながら、同時にテーブルアイテムをフィルタリングする方法を説明します。

使うデータと基本のテーブル

今回は、2019年から2022年までに開催された、もしくはされる予定のサッカーの国際大会決勝をドロップダウンで年、月を絞り込みながら表示アイテムを絞り込んでいく、というシナリオを考えます。
使用するデータは以下の通りです。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-tag"><<span class="hljs-name">template</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">b-table</span>
<span class="hljs-attr">class</span>=<span class="hljs-string">"text-left"</span>
<span class="hljs-attr">:items</span>=<span class="hljs-string">"items"</span>
></span>>
<span class="hljs-tag"></<span class="hljs-name">b-table</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">template</span>></span>
<span class="hljs-tag"><<span class="hljs-name">template</span>></span> <span class="hljs-tag"><<span class="hljs-name">div</span>></span> <span class="hljs-tag"><<span class="hljs-name">b-table</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-left"</span> <span class="hljs-attr">:items</span>=<span class="hljs-string">"items"</span> ></span>> <span class="hljs-tag"></<span class="hljs-name">b-table</span>></span> <span class="hljs-tag"></<span class="hljs-name">div</span>></span> <span class="hljs-tag"></<span class="hljs-name">template</span>></span>
<template>
  <div>
    <b-table
      class="text-left"
      :items="items"
    >>
    </b-table>
  </div>
</template>
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<script>
export <span class="hljs-keyword">default</span> {
data() {
<span class="hljs-keyword">return</span> {
items: <span class="hljs-keyword">null</span>,
}
},
mounted() {
<span class="hljs-keyword">this</span>.items = DATA
},
}
<span class="hljs-keyword">const</span> DATA = [
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2019</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">2</span>, sports_event: <span class="hljs-string">'2019 AFC Asian Cup Final'</span> },
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2019</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">7</span>, sports_event: <span class="hljs-string">'2019 FIFA Women\'s World Cup Final'</span> },
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">1</span>, sports_event: <span class="hljs-string">'2020 African Nations Championship Final'</span> },
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">2</span>, sports_event: <span class="hljs-string">'2020 FIFA Club World Cup Final'</span> },
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">7</span>, sports_event: <span class="hljs-string">'UEFA Euro 2020 Final'</span> },
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2022</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">12</span>, sports_event: <span class="hljs-string">'2022 FIFA World Cup Final'</span> },
]
</script>
<script> export <span class="hljs-keyword">default</span> { data() { <span class="hljs-keyword">return</span> { items: <span class="hljs-keyword">null</span>, } }, mounted() { <span class="hljs-keyword">this</span>.items = DATA }, } <span class="hljs-keyword">const</span> DATA = [ { <span class="hljs-built_in">year</span>: <span class="hljs-number">2019</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">2</span>, sports_event: <span class="hljs-string">'2019 AFC Asian Cup Final'</span> }, { <span class="hljs-built_in">year</span>: <span class="hljs-number">2019</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">7</span>, sports_event: <span class="hljs-string">'2019 FIFA Women\'s World Cup Final'</span> }, { <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">1</span>, sports_event: <span class="hljs-string">'2020 African Nations Championship Final'</span> }, { <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">2</span>, sports_event: <span class="hljs-string">'2020 FIFA Club World Cup Final'</span> }, { <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">7</span>, sports_event: <span class="hljs-string">'UEFA Euro 2020 Final'</span> }, { <span class="hljs-built_in">year</span>: <span class="hljs-number">2022</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">12</span>, sports_event: <span class="hljs-string">'2022 FIFA World Cup Final'</span> }, ] </script>
<script>
export default {
  data() {
    return {
      items: null,
    }
  },
  mounted() {
    this.items = DATA
  },
}

const DATA = [
  { year: 2019, month: 2, sports_event: '2019 AFC Asian Cup Final' },
  { year: 2019, month: 7, sports_event: '2019 FIFA Women\'s World Cup Final' },
  { year: 2021, month: 1, sports_event: '2020 African Nations Championship Final' },
  { year: 2021, month: 2, sports_event: '2020 FIFA Club World Cup Final' },
  { year: 2021, month: 7, sports_event: 'UEFA Euro 2020 Final' },
  { year: 2022, month: 12, sports_event: '2022 FIFA World Cup Final' },
]
</script>

ドロップダウン(b-form-select)の設置

まずは、絞り込み用のドロップダウンを設置していきます。今回は、年、月の2つのドロップダウンを設置していきます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<<span class="hljs-keyword">template</span>>
<div>
<b-form-<span class="hljs-keyword">select</span>
v-model="year"
:<span class="hljs-keyword">options</span>="year_list"
<span class="hljs-keyword">class</span>="mb-3"
></b-form-<span class="hljs-keyword">select</span>>
<b-form-<span class="hljs-keyword">select</span>
v-model="month"
:<span class="hljs-keyword">options</span>="month_list"
<span class="hljs-keyword">class</span>="mb-3"
></b-form-<span class="hljs-keyword">select</span>>
<b-<span class="hljs-keyword">table</span>
<span class="hljs-keyword">class</span>="text-left"
:items="items"
></b-<span class="hljs-keyword">table</span>>
</div>
</<span class="hljs-keyword">template</span>>
<<span class="hljs-keyword">template</span>> <div> <b-form-<span class="hljs-keyword">select</span> v-model="year" :<span class="hljs-keyword">options</span>="year_list" <span class="hljs-keyword">class</span>="mb-3" ></b-form-<span class="hljs-keyword">select</span>> <b-form-<span class="hljs-keyword">select</span> v-model="month" :<span class="hljs-keyword">options</span>="month_list" <span class="hljs-keyword">class</span>="mb-3" ></b-form-<span class="hljs-keyword">select</span>> <b-<span class="hljs-keyword">table</span> <span class="hljs-keyword">class</span>="text-left" :items="items" ></b-<span class="hljs-keyword">table</span>> </div> </<span class="hljs-keyword">template</span>>
<template>
  <div>
    <b-form-select
      v-model="year"
      :options="year_list"
      class="mb-3"
    ></b-form-select>
    <b-form-select
      v-model="month"
      :options="month_list"
      class="mb-3"
    ></b-form-select>
    <b-table
      class="text-left"
      :items="items"
    ></b-table>
  </div>
</template>

データプロパティには、ドロップダウンで選択した値を保持するyearと、ドロップダウンに表示するリストを保持するyear_listを用意します。月も同様です。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-builtin-name">export</span><span class="hljs-built_in"> default </span>{
data() {
return {
items: <span class="hljs-literal">null</span>,
year: <span class="hljs-string">""</span>,
year_list: [],
month: <span class="hljs-string">""</span>,
month_list: [],
}
},
mounted() {
this.items = DATA
},
}
<span class="hljs-builtin-name">export</span><span class="hljs-built_in"> default </span>{ data() { return { items: <span class="hljs-literal">null</span>, year: <span class="hljs-string">""</span>, year_list: [], month: <span class="hljs-string">""</span>, month_list: [], } }, mounted() { this.items = DATA }, }
export default {
  data() {
    return {
      items: null,
      year: "",
      year_list: [],
      month: "",
      month_list: [],
    }
  },
  mounted() {
    this.items = DATA
  },
}

ドロップダウンに表示するリストを作成します。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-function"><span class="hljs-title">mounted</span><span class="hljs-params">()</span></span> {
this<span class="hljs-selector-class">.items</span> = DATA
DATA.map(item => this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.push</span>(item.year))
DATA.map(item => this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.push</span>(item.month))
},
<span class="hljs-function"><span class="hljs-title">mounted</span><span class="hljs-params">()</span></span> { this<span class="hljs-selector-class">.items</span> = DATA DATA.map(item => this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.push</span>(item.year)) DATA.map(item => this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.push</span>(item.month)) },
mounted() {
    this.items = DATA
    DATA.map(item => this.year_list.push(item.year))
    DATA.map(item => this.month_list.push(item.month))
  },

年、月共にリストに値が入りましたが、重複データもありますし、ソートもされていませんので、重複を排除し、ソートすることにします。

重複排除、ソート

重複の排除には以下のようなアロー関数を使うことにします。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-function"><span class="hljs-title">mounted</span><span class="hljs-params">()</span></span> {
this<span class="hljs-selector-class">.items</span> = DATA
DATA.map(item => this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.push</span>(item.year))
DATA.map(item => this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.push</span>(item.month))
this<span class="hljs-selector-class">.year_list</span> = this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.filter</span>((item, index) => this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.indexOf</span>(item) == index)
this<span class="hljs-selector-class">.month_list</span> = this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.filter</span>((item, index) => this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.indexOf</span>(item) == index)
},
<span class="hljs-function"><span class="hljs-title">mounted</span><span class="hljs-params">()</span></span> { this<span class="hljs-selector-class">.items</span> = DATA DATA.map(item => this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.push</span>(item.year)) DATA.map(item => this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.push</span>(item.month)) this<span class="hljs-selector-class">.year_list</span> = this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.filter</span>((item, index) => this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.indexOf</span>(item) == index) this<span class="hljs-selector-class">.month_list</span> = this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.filter</span>((item, index) => this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.indexOf</span>(item) == index) },
mounted() {
    this.items = DATA
    DATA.map(item => this.year_list.push(item.year))
    DATA.map(item => this.month_list.push(item.month))

    this.year_list = this.year_list.filter((item, index) => this.year_list.indexOf(item) == index)
    this.month_list = this.month_list.filter((item, index) => this.month_list.indexOf(item) == index)
  },

重複が排除され、ドロップダウンがすっきりしました。次に、ソートをすることにします。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-function"><span class="hljs-title">mounted</span><span class="hljs-params">()</span></span> {
this<span class="hljs-selector-class">.items</span> = DATA
DATA.map(item => this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.push</span>(item.year))
DATA.map(item => this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.push</span>(item.month))
this<span class="hljs-selector-class">.year_list</span> = this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.filter</span>((item, index) => this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.indexOf</span>(item) == index)
this<span class="hljs-selector-class">.month_list</span> = this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.filter</span>((item, index) => this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.indexOf</span>(item) == index)
this<span class="hljs-selector-class">.year_list</span> = this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.sort</span>((<span class="hljs-selector-tag">a</span>, b) => <span class="hljs-selector-tag">a</span> - b)
this<span class="hljs-selector-class">.month_list</span> = this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.sort</span>((<span class="hljs-selector-tag">a</span>, b) => <span class="hljs-selector-tag">a</span> - b)
},
<span class="hljs-function"><span class="hljs-title">mounted</span><span class="hljs-params">()</span></span> { this<span class="hljs-selector-class">.items</span> = DATA DATA.map(item => this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.push</span>(item.year)) DATA.map(item => this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.push</span>(item.month)) this<span class="hljs-selector-class">.year_list</span> = this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.filter</span>((item, index) => this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.indexOf</span>(item) == index) this<span class="hljs-selector-class">.month_list</span> = this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.filter</span>((item, index) => this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.indexOf</span>(item) == index) this<span class="hljs-selector-class">.year_list</span> = this<span class="hljs-selector-class">.year_list</span><span class="hljs-selector-class">.sort</span>((<span class="hljs-selector-tag">a</span>, b) => <span class="hljs-selector-tag">a</span> - b) this<span class="hljs-selector-class">.month_list</span> = this<span class="hljs-selector-class">.month_list</span><span class="hljs-selector-class">.sort</span>((<span class="hljs-selector-tag">a</span>, b) => <span class="hljs-selector-tag">a</span> - b) },
mounted() {
    this.items = DATA
    DATA.map(item => this.year_list.push(item.year))
    DATA.map(item => this.month_list.push(item.month))

    this.year_list = this.year_list.filter((item, index) => this.year_list.indexOf(item) == index)
    this.month_list = this.month_list.filter((item, index) => this.month_list.indexOf(item) == index)

    this.year_list = this.year_list.sort((a, b) => a - b)
    this.month_list = this.month_list.sort((a, b) => a - b)
  },

これで、検索用のドロップダウンの設置が完了しました。この状態では、ドロップダウンを選択しても特に何もおこりません。次に、本題である、ドロップダウンの内容を動的にフィルタリングするようにしてみます。

年(Year)の内容で、月(Month)のリスト項目を絞り込み

ここでは、例えばYearドロップダウンで2021を選択した際に、Monthドロップダウンとして、1, 2, 7のみが表示されるように、Year, Monthの順でNarrow Downするようにしてみます。今回はwatchプロパティを使う方法で実装してみます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
watch: {
<span class="hljs-attribute">year</span>: function (newVal) {
this<span class="hljs-variable">.month_list</span> = []
DATA<span class="hljs-variable">.map</span>(item =>
(item<span class="hljs-variable">.year</span> == newVal && this<span class="hljs-variable">.month_list</span><span class="hljs-variable">.push</span>(item<span class="hljs-variable">.month</span>))
)
},
},
watch: { <span class="hljs-attribute">year</span>: function (newVal) { this<span class="hljs-variable">.month_list</span> = [] DATA<span class="hljs-variable">.map</span>(item => (item<span class="hljs-variable">.year</span> == newVal && this<span class="hljs-variable">.month_list</span><span class="hljs-variable">.push</span>(item<span class="hljs-variable">.month</span>)) ) }, },
watch: {
    year: function (newVal) {
      this.month_list = []
      DATA.map(item =>
        (item.year == newVal && this.month_list.push(item.month))
      )
    },
  },

ドロップダウンの値が変更されると、このfunctionが呼び出され、選択した値がnewValとして連携されますので、まずはmonthドロップダウンのリストに表示するプロパティのmonth_listを初期化し、データの中から選択されたyearのものだけをmonth_listに格納し、monthドロップダウンに表示するようにしています。このコードを追加すると、以下のような振る舞いになります。

これで、1つ目のドロップダウンの値に2つ目のドロップダウンの値が連動し、動的にドロップダウンの表示項目が変化するようになりました。最後に、この2つのドロップダウンの値に、テーブルアイテムを連動させてみます。

テーブル(b-table)をドロップダウン(b-form-select)の内容でフィルタリング

以下の投稿で説明した方法を、ほぼそのまま流用することで、ドロップダウンの値とテーブルを連動させてみます。細かい部分は、以下の投稿を参考にしてみてください。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<b-<span class="hljs-keyword">table</span>
<span class="hljs-keyword">class</span>="text-left"
:items="items"
:<span class="hljs-keyword">filter</span>="filter"
:<span class="hljs-keyword">filter</span>-<span class="hljs-keyword">function</span>="tableFilter"
></b-<span class="hljs-keyword">table</span>>
<b-<span class="hljs-keyword">table</span> <span class="hljs-keyword">class</span>="text-left" :items="items" :<span class="hljs-keyword">filter</span>="filter" :<span class="hljs-keyword">filter</span>-<span class="hljs-keyword">function</span>="tableFilter" ></b-<span class="hljs-keyword">table</span>>
<b-table
      class="text-left"
      :items="items"
      :filter="filter"
      :filter-function="tableFilter"
></b-table>
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
methods: {
tableFilter(row) {
var filter_year = <span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span> ? <span class="hljs-keyword">String</span>(row.<span class="hljs-built_in">year</span>) == <span class="hljs-keyword">String</span>(<span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span>) : <span class="hljs-keyword">true</span>
var filter_month = <span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span> ? <span class="hljs-keyword">String</span>(row.<span class="hljs-built_in">month</span>) == <span class="hljs-keyword">String</span>(<span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span>) : <span class="hljs-keyword">true</span>
<span class="hljs-keyword">return</span> filter_year && filter_month
}
},
computed: {
<span class="hljs-built_in">filter</span>: function () {
<span class="hljs-keyword">return</span> [<span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span>, <span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span>]
}
},
methods: { tableFilter(row) { var filter_year = <span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span> ? <span class="hljs-keyword">String</span>(row.<span class="hljs-built_in">year</span>) == <span class="hljs-keyword">String</span>(<span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span>) : <span class="hljs-keyword">true</span> var filter_month = <span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span> ? <span class="hljs-keyword">String</span>(row.<span class="hljs-built_in">month</span>) == <span class="hljs-keyword">String</span>(<span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span>) : <span class="hljs-keyword">true</span> <span class="hljs-keyword">return</span> filter_year && filter_month } }, computed: { <span class="hljs-built_in">filter</span>: function () { <span class="hljs-keyword">return</span> [<span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span>, <span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span>] } },
methods: {
    tableFilter(row) {
      var filter_year = this.year ? String(row.year) == String(this.year) : true
      var filter_month = this.month ? String(row.month) == String(this.month) : true

      return filter_year && filter_month
    }
  },
computed: {
    filter: function () {
      return [this.year, this.month]
    }
  },

上記を実装した結果は以下の通りです。テーブルアイテムが絞り込めて表示できていることが分かると思います。

まとめ

2022年を選択した際に一度テーブルが消えてしまう、一度値を選択すると全検索(当該項目でのフィルタリングなし)ができない、など実用上はもう少しブラッシュアップが必要かと思いますが、冗長になってしまうので、今回はここまでとします。

最終型のソースコード

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<<span class="hljs-keyword">template</span>>
<div>
<b-form-<span class="hljs-keyword">select</span>
v-model="year"
:<span class="hljs-keyword">options</span>="year_list"
<span class="hljs-keyword">class</span>="mb-3"
></b-form-<span class="hljs-keyword">select</span>>
<b-form-<span class="hljs-keyword">select</span>
v-model="month"
:<span class="hljs-keyword">options</span>="month_list"
<span class="hljs-keyword">class</span>="mb-3"
></b-form-<span class="hljs-keyword">select</span>>
<b-<span class="hljs-keyword">table</span>
<span class="hljs-keyword">class</span>="text-left"
:items="items"
:<span class="hljs-keyword">filter</span>="filter"
:<span class="hljs-keyword">filter</span>-<span class="hljs-keyword">function</span>="tableFilter"
></b-<span class="hljs-keyword">table</span>>
</div>
</<span class="hljs-keyword">template</span>>
<<span class="hljs-keyword">template</span>> <div> <b-form-<span class="hljs-keyword">select</span> v-model="year" :<span class="hljs-keyword">options</span>="year_list" <span class="hljs-keyword">class</span>="mb-3" ></b-form-<span class="hljs-keyword">select</span>> <b-form-<span class="hljs-keyword">select</span> v-model="month" :<span class="hljs-keyword">options</span>="month_list" <span class="hljs-keyword">class</span>="mb-3" ></b-form-<span class="hljs-keyword">select</span>> <b-<span class="hljs-keyword">table</span> <span class="hljs-keyword">class</span>="text-left" :items="items" :<span class="hljs-keyword">filter</span>="filter" :<span class="hljs-keyword">filter</span>-<span class="hljs-keyword">function</span>="tableFilter" ></b-<span class="hljs-keyword">table</span>> </div> </<span class="hljs-keyword">template</span>>
<template>
  <div>
    <b-form-select
      v-model="year"
      :options="year_list"
      class="mb-3"
    ></b-form-select>
    <b-form-select
      v-model="month"
      :options="month_list"
      class="mb-3"
    ></b-form-select>
    <b-table
      class="text-left"
      :items="items"
      :filter="filter"
      :filter-function="tableFilter"
    ></b-table>
  </div>
</template>
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<script>
export <span class="hljs-keyword">default</span> {
data() {
<span class="hljs-keyword">return</span> {
items: <span class="hljs-keyword">null</span>,
criteria: <span class="hljs-string">""</span>,
<span class="hljs-built_in">year</span>: <span class="hljs-string">""</span>,
year_list: [],
<span class="hljs-built_in">month</span>: <span class="hljs-string">""</span>,
month_list: [],
}
},
methods: {
tableFilter(row) {
var filter_year = <span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span> ? <span class="hljs-keyword">String</span>(row.<span class="hljs-built_in">year</span>) == <span class="hljs-keyword">String</span>(<span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span>) : <span class="hljs-keyword">true</span>
var filter_month = <span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span> ? <span class="hljs-keyword">String</span>(row.<span class="hljs-built_in">month</span>) == <span class="hljs-keyword">String</span>(<span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span>) : <span class="hljs-keyword">true</span>
<span class="hljs-keyword">return</span> filter_year && filter_month
}
},
computed: {
<span class="hljs-built_in">filter</span>: function () {
<span class="hljs-keyword">return</span> [<span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span>, <span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span>]
}
},
watch: {
<span class="hljs-built_in">year</span>: function (newVal) {
<span class="hljs-keyword">this</span>.month_list = []
DATA.<span class="hljs-built_in">map</span>(item =>
(item.<span class="hljs-built_in">year</span> == newVal && <span class="hljs-keyword">this</span>.month_list.push(item.<span class="hljs-built_in">month</span>))
)
},
},
mounted() {
<span class="hljs-keyword">this</span>.items = DATA
DATA.<span class="hljs-built_in">map</span>(item => <span class="hljs-keyword">this</span>.year_list.push(item.<span class="hljs-built_in">year</span>))
DATA.<span class="hljs-built_in">map</span>(item => <span class="hljs-keyword">this</span>.month_list.push(item.<span class="hljs-built_in">month</span>))
<span class="hljs-keyword">this</span>.year_list = <span class="hljs-keyword">this</span>.year_list.<span class="hljs-built_in">filter</span>((item, index) => <span class="hljs-keyword">this</span>.year_list.indexOf(item) == index)
<span class="hljs-keyword">this</span>.month_list = <span class="hljs-keyword">this</span>.month_list.<span class="hljs-built_in">filter</span>((item, index) => <span class="hljs-keyword">this</span>.month_list.indexOf(item) == index)
<span class="hljs-keyword">this</span>.year_list = <span class="hljs-keyword">this</span>.year_list.<span class="hljs-built_in">sort</span>((a, b) => a - b)
<span class="hljs-keyword">this</span>.month_list = <span class="hljs-keyword">this</span>.month_list.<span class="hljs-built_in">sort</span>((a, b) => a - b)
},
}
<span class="hljs-keyword">const</span> DATA = [
<span class="hljs-comment">// https://en.wikipedia.org/wiki/2021_in_association_football</span>
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2019</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">2</span>, sports_event: <span class="hljs-string">'2019 AFC Asian Cup Final'</span> },
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2019</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">7</span>, sports_event: <span class="hljs-string">'2019 FIFA Women\'s World Cup Final'</span> },
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">1</span>, sports_event: <span class="hljs-string">'2020 African Nations Championship Final'</span> },
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">2</span>, sports_event: <span class="hljs-string">'2020 FIFA Club World Cup Final'</span> },
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">7</span>, sports_event: <span class="hljs-string">'UEFA Euro 2020 Final'</span> },
{ <span class="hljs-built_in">year</span>: <span class="hljs-number">2022</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">12</span>, sports_event: <span class="hljs-string">'2022 FIFA World Cup Final'</span> },
]
</script>
<script> export <span class="hljs-keyword">default</span> { data() { <span class="hljs-keyword">return</span> { items: <span class="hljs-keyword">null</span>, criteria: <span class="hljs-string">""</span>, <span class="hljs-built_in">year</span>: <span class="hljs-string">""</span>, year_list: [], <span class="hljs-built_in">month</span>: <span class="hljs-string">""</span>, month_list: [], } }, methods: { tableFilter(row) { var filter_year = <span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span> ? <span class="hljs-keyword">String</span>(row.<span class="hljs-built_in">year</span>) == <span class="hljs-keyword">String</span>(<span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span>) : <span class="hljs-keyword">true</span> var filter_month = <span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span> ? <span class="hljs-keyword">String</span>(row.<span class="hljs-built_in">month</span>) == <span class="hljs-keyword">String</span>(<span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span>) : <span class="hljs-keyword">true</span> <span class="hljs-keyword">return</span> filter_year && filter_month } }, computed: { <span class="hljs-built_in">filter</span>: function () { <span class="hljs-keyword">return</span> [<span class="hljs-keyword">this</span>.<span class="hljs-built_in">year</span>, <span class="hljs-keyword">this</span>.<span class="hljs-built_in">month</span>] } }, watch: { <span class="hljs-built_in">year</span>: function (newVal) { <span class="hljs-keyword">this</span>.month_list = [] DATA.<span class="hljs-built_in">map</span>(item => (item.<span class="hljs-built_in">year</span> == newVal && <span class="hljs-keyword">this</span>.month_list.push(item.<span class="hljs-built_in">month</span>)) ) }, }, mounted() { <span class="hljs-keyword">this</span>.items = DATA DATA.<span class="hljs-built_in">map</span>(item => <span class="hljs-keyword">this</span>.year_list.push(item.<span class="hljs-built_in">year</span>)) DATA.<span class="hljs-built_in">map</span>(item => <span class="hljs-keyword">this</span>.month_list.push(item.<span class="hljs-built_in">month</span>)) <span class="hljs-keyword">this</span>.year_list = <span class="hljs-keyword">this</span>.year_list.<span class="hljs-built_in">filter</span>((item, index) => <span class="hljs-keyword">this</span>.year_list.indexOf(item) == index) <span class="hljs-keyword">this</span>.month_list = <span class="hljs-keyword">this</span>.month_list.<span class="hljs-built_in">filter</span>((item, index) => <span class="hljs-keyword">this</span>.month_list.indexOf(item) == index) <span class="hljs-keyword">this</span>.year_list = <span class="hljs-keyword">this</span>.year_list.<span class="hljs-built_in">sort</span>((a, b) => a - b) <span class="hljs-keyword">this</span>.month_list = <span class="hljs-keyword">this</span>.month_list.<span class="hljs-built_in">sort</span>((a, b) => a - b) }, } <span class="hljs-keyword">const</span> DATA = [ <span class="hljs-comment">// https://en.wikipedia.org/wiki/2021_in_association_football</span> { <span class="hljs-built_in">year</span>: <span class="hljs-number">2019</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">2</span>, sports_event: <span class="hljs-string">'2019 AFC Asian Cup Final'</span> }, { <span class="hljs-built_in">year</span>: <span class="hljs-number">2019</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">7</span>, sports_event: <span class="hljs-string">'2019 FIFA Women\'s World Cup Final'</span> }, { <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">1</span>, sports_event: <span class="hljs-string">'2020 African Nations Championship Final'</span> }, { <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">2</span>, sports_event: <span class="hljs-string">'2020 FIFA Club World Cup Final'</span> }, { <span class="hljs-built_in">year</span>: <span class="hljs-number">2021</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">7</span>, sports_event: <span class="hljs-string">'UEFA Euro 2020 Final'</span> }, { <span class="hljs-built_in">year</span>: <span class="hljs-number">2022</span>, <span class="hljs-built_in">month</span>: <span class="hljs-number">12</span>, sports_event: <span class="hljs-string">'2022 FIFA World Cup Final'</span> }, ] </script>
<script>
export default {
  data() {
    return {
      items: null,
      criteria: "",
      year: "",
      year_list: [],
      month: "",
      month_list: [],
    }
  },
  methods: {
    tableFilter(row) {
      var filter_year = this.year ? String(row.year) == String(this.year) : true
      var filter_month = this.month ? String(row.month) == String(this.month) : true

      return filter_year && filter_month
    }
  },
  computed: {
    filter: function () {
      return [this.year, this.month]
    }
  },
  watch: {
    year: function (newVal) {
      this.month_list = []
      DATA.map(item =>
        (item.year == newVal && this.month_list.push(item.month))
      )
    },
  },
  mounted() {
    this.items = DATA
    DATA.map(item => this.year_list.push(item.year))
    DATA.map(item => this.month_list.push(item.month))

    this.year_list = this.year_list.filter((item, index) => this.year_list.indexOf(item) == index)
    this.month_list = this.month_list.filter((item, index) => this.month_list.indexOf(item) == index)

    this.year_list = this.year_list.sort((a, b) => a - b)
    this.month_list = this.month_list.sort((a, b) => a - b)
  },
}

const DATA = [
  // https://en.wikipedia.org/wiki/2021_in_association_football
  { year: 2019, month: 2, sports_event: '2019 AFC Asian Cup Final' },
  { year: 2019, month: 7, sports_event: '2019 FIFA Women\'s World Cup Final' },
  { year: 2021, month: 1, sports_event: '2020 African Nations Championship Final' },
  { year: 2021, month: 2, sports_event: '2020 FIFA Club World Cup Final' },
  { year: 2021, month: 7, sports_event: 'UEFA Euro 2020 Final' },
  { year: 2022, month: 12, sports_event: '2022 FIFA World Cup Final' },
]
</script>

余談ですが、wikipediaを参考に今回のサンプルデータを作成しましたが、2020年のイベントが軒並み2021年に延期されていることを再認識せざるを得ませんでした…

Ads