"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

Select選択値の変数へのバインドと、@changeイベントハンドリング/NUXT自己流チュートリアル(4)

今回は、Selectの選択値の変数へのバインドと、@change(v-on:changeでも可)を使ったイベントハンドリングでメソッドを呼んで、もうひとつのSelectの内容を更新するってのをやってみます。

f:id:arakan_no_boku:20190509225706p:plain

事前に頭にいれておくこと

 

イベントをトリガにしてJavaScriptの関数を実行して結果を更新する。

そのトリガになるイベントとして、 NUXT自己流チュートリアル(3)では、onClickイベントを例にしましたが、もうひとつ重要な「onChange」イベントを扱います。

v-onと省略形の「@」のどちらでも使えるので。

  • v-on:change
  • @change

のいずれかを利用することになります。

あと、<Select>を使います。

選択された値を格納する変数を紐づけるのに「v-model」を使うのですが、選択されて変数に格納されるのは「value」プロパティの値です。

 

ちょっとだけ補足

 

別記事で紹介する予定ではいますが、<select>についてひとつだけ補足です。

今回はUIフレームワークは使わないのですが、「Buefy」で拡張された<b-select>というのがあります。

一応、「NUXT自己流チュートリアル(6)」あたりでとりあげる予定ですが、困ったことに、<b-select>だと、@changeでうまくイベントが拾えません。 

今回は、<select>なので@changeでイベントトリガにしてますが、もし<b-select>に変更したら、@changeではイベントは拾えず、@inputに変更する必要があったりしまうので、ちょっと頭の隅にでも置いといてもらえるといいかも・・です。

 

今回の記事の前提的なこと

 

自己流チュートリアル(1)で「前提」と「チュートリアルの準備」として書いていることは、できている必要があります。

つまり。

インストール・環境設定・テスト専用Chromeショートカットの作成うんぬんですね。

まだの方は、下記記事を先に参照して、環境設定をお願いします。

arakan-pgm-ai.hatenablog.com

 

あと、都道府県・市町村データ取得のWEB-APIを使います。

API-KEYが必要になるので、まだ取得していない場合は、以下で登録してAPI-KEYを取得しておいてください。

opendata.resas-portal.go.jp

 

今回の目的

 

NUXT自己流チュートリアル(2)で都道府県コード固定でWEB-APIからデータの取得と<table>を使った表示をやりました。 

ソースは「cityapi.vue」です。

今回は、そこを変更して、都道府県情報・市町村情報共、Selectにします。 

新たに必要になる技術要素は。

  • Selectで選択されているコードを変数におさめる(選択バインディング
  • Selectにイベントトリガ(@change)をつけて、市町村取得メソッドを実行させる。

みたいなことです。 

 

ソースコードです

 

全体的には、NUXT自己流チュートリアル(2)をベースにします。

その中の「cityapi.vue」だけを変更していくことになります。

処理概要を簡単に書くと。

NUXT自己流チュートリアル(2)では都道府県コード固定でしたが、今回は。

  1. 初期処理で都道府県のリストを取得して、上段の「Select」にセットする。
  2. 上段の「Select」で都道府県が選択された(onChange)のをひろう。
  3. 上記をトリガにして、市区町村情報を取得しなおす。
  4. 取得した市区町村情報を、下段の「Select」を更新する。

ということをやります。

修正後のソース全体がこちらです。

pages/cityapi.vue 

<template>
  <div>
    <NLink to="/">
      ルートのページへ戻ります
    </NLink>
    <br/>
    <img src="/jamap.JPG" alt="image03" />
    <div v-if=" prefecturesJson.message == null">
        <select v-model="prefecturesSelected" v-on:change="updateMunicipalitiesJson({prefecturesSelected})">
          <option value=""></option>
          <option v-for="pOption in prefecturesJson.result" v-bind:key="pOption.id" v-bind:value="pOption.prefCode">
            {{pOption.prefName}}
          </option>
        </select>    
    </div>
    <div v-if="municipalitiesJson != null">
      <div v-if="municipalitiesJson.message == null">
        <select v-model="municipalitiesSelected">
          <option v-for="mOption in municipalitiesJson.result" v-bind:key="mOption.id" v-bind:value="mOption.cityCode">
            {{mOption.cityName}}
          </option>
        </select>    
      </div>
    </div>  
    <div v-else>
        <select v-model="municipalitiesSelected">
          <option value=""></option>
        </select>  
    </div>  
  </div>
</template>

<script>
import axios from 'axios'
export default {
  async asyncData() {
    return await axios
    .get('https://opendata.resas-portal.go.jp/api/v1/prefectures',{
      headers:{
        "X-API-KEY":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXOjK"
      },
      data:{}
    })
    .then((res) => {
      return { prefecturesJson: res.data }
    })
  },
  data(){
    return{
      prefecturesSelected:'',
      municipalitiesSelected:'',
      municipalitiesJson:null
    }
  },
  methods:{
    async updateMunicipalitiesJson({prefecturesSelected}){
      let url =  `https://opendata.resas-portal.go.jp/api/v1/cities?prefCode=${prefecturesSelected} `
      return await axios
      .get(url,{
        headers:{
          "X-API-KEY":"XXXXXXXXXXXXXXXXXOjK"
        },
        data:{}
      })
      .then((res) => {
        this.municipalitiesJson =  res.data
      })
    }  
  },
  head: {
    title: 'CityApi page'
  }
}
</script>

ポイントを確認していきます。

 

変数の定義と初期化

 

まず、変数の定義と初期化です。

data()の中で

prefecturesSelected:'',
municipalitiesSelected:'',
municipalitiesJson:null

 を定義・初期化しています。

これを忘れると変数が未定義だと怒られます。

都道府県データをおさめる「prefecturesJson」は、asincData()の中で取得して初期セットしているので、こちらには書きません。

 

Selectへの情報セットと変数へのバインド

 

Selectの中で選択されたコードを収める変数は、「v-model」でひもつけます。

<select v-model="municipalitiesSelected">

 や

<select v-model="municipalitiesSelected">

な感じです。

そこで収められるのは<option>タグのvalueの値です。

APIで取得した「prefecturesJson」や「municipalitiesJson」に収めたデータは、「v-for」のループでおさめていきます。

市町村データ「municipalitiesJson」の場合でいくと。

<option v-for="mOption in municipalitiesJson.result" v-bind:key="mOption.id" v-bind:value="mOption.cityCode">

という感じになります。

v-for="mOption in municipalitiesJson.result" v-bind:key="mOption.id"

までは、NUXT自己流チュートリアル(2)で説明したのと同じですが

今回の場合は後ろに以下がついてます。

v-bind:value="mOption.cityCode"

つまり、optionのvalueに、json内のcityCodeをセットしています。

 

@changeでonChangeイベントを拾う

 

もうひとつのポイントはこちらです。

<select v-model="prefecturesSelected" @change="update_municipalitiesJson({prefecturesSelected})">

都道府県のSelectに「@change」で「updateMunicipalitiesJson({prefecturesSelected})」メソッドを紐付けます。

このメソッドは「 methods:」の中で定義していて、選択された都道府県コードをキーに、中で市町村情報を取得するAPIを使ってデータを取得し、「this.municipalitiesJson = res.data」で、市町村情報のSELECTの内容を書き換えているわけです。

 

さて実行してみます

 

プロジェクトをカレントフォルダにして「npm run dev」して、「http://localhost:3000」で表示します。

もちろん、Originチェックを回避できる「テスト用ショートカット」から起動したものですよ。

さて。

f:id:arakan_no_boku:20190516234656p:plain

ここから「市区町村のサンプル」のリンクをクリックします。

f:id:arakan_no_boku:20190516234814p:plain

都道府県のSELECTを開いたところです。

ここで、東京でも選んでみます。

f:id:arakan_no_boku:20190516234944p:plain

スパっと、東京都の市区町村が表示されます。

いい感じですねえ。

今回は、こんなところで。

ではでは。