"BOKU"のITな日常

BOKUが勉強したり、考えたことを頭の整理を兼ねてまとめてます。

Nuxtアプリケーションで使うVue.js/Select選択値の変数バインドと@changeイベントハンドリング

f:id:arakan_no_boku:20190509225706p:plain

目次

はじめに

リライトして目次を追加しました。

内容は2019年5月当時のままです。

僕がNuxt.jsの各機能を理解するために、ひとつひとつ確認したことをまとめていこうと考えています。

インストール・環境構築は、以下の手順でできている前提です。

arakan-pgm-ai.hatenablog.com

Nuxt.jsを整理する方針

Nuxt.js関連資料やサンプルソースを見ると混乱することが多いのは、Nuxt.jsはVue.jsの機能を包含していて、ひとつのソースの中で、どれがNuxt.js特有の機能で、どれがVue.jsの機能かの区別がつけにくいからだと感じています。

その混在しているイメージを図にしてみると、こんな感じに見えます。

f:id:arakan_no_boku:20190511100242p:plain

なので、僕はアプローチとして、各技術要素にわけて、一回に少しずつ要素を確認していくことにしました。

分け方としては、以下のようになると考えています。

  1. Nuxt.js独自の要素ー基本
  2. Vue.js独自の要素
  3. BulmaのCSS要素(Burfyのclassは、Bulmaを使っている場合が多い)
  4. Buefy独自の要素
  5. Nuxt.js独自の要素ー応用
  6. テストフレームワーク他モジュールの要素

今回は、Nuxtで使うVue.js独自要素の確認の一環で、onChangeイベントの取り扱いを中心に整理したいと思ってます。

サンプルコード1

Selectの選択値の変数へのバインドと、2つのSelectを並べて、片方の選択内容にあわせて、もうひとつのSelectの内容を更新するのをやってみます。

今回は。

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

ということをやります。

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

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

みたいなことです。 

ソース全体がこちらです。

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" @change="updateMunicipalitiesJson({prefecturesSelected})">
        <option value="" />
        <option v-for="pOption in prefecturesJson.result" :key="pOption.id" :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" :key="mOption.id" :value="mOption.cityCode">
            {{ mOption.cityName }}
          </option>
        </select>
      </div>
    </div>
    <div v-else>
      <select v-model="municipalitiesSelected">
        <option value="" />
      </select>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  data () {
    return {
      prefecturesSelected: '',
      municipalitiesSelected: '',
      municipalitiesJson: null
    }
  },
  asyncData () {
    return axios
      .get('https://opendata.resas-portal.go.jp/api/v1/prefectures', {
        headers: {
          'X-API-KEY': 'noxxxxxxxxxxxxxxxxxxxxxxxxxOjK'
        },
        data: {}
      })
      .then((res) => {
        return { prefecturesJson: res.data }
      })
  },
  methods: {
    async updateMunicipalitiesJson ({ prefecturesSelected }) {
      const url = `https://opendata.resas-portal.go.jp/api/v1/cities?prefCode=${prefecturesSelected} `
      await axios
        .get(url, {
          headers: {
            'X-API-KEY': 'noxxxxxxxxxxxxxxxxxxxxxxxxOjK'
          },
          data: {}
        })
        .then((res) => {
          this.municipalitiesJson = res.data
        })
      return this.municipalitiesJson
    }
  },
  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の内容を書き換えているわけです。

onChangeイベントはv-onと省略形の「@」のどちらでも使えるので。

  • v-on:change
  • @change

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

今回は<Select>タグを使うので、@changeでイベントトリガを使います。

ただ、今回はとりあげていませんが、UIフレームワーク「Buefy」には拡張された<b-select>というのもあります。

サンプルでよくでてくるのは、こちらだったりしまうが、<b-select>だと、@changeでうまくイベントが拾えない点に注意が必要です。(<b-select>を使う場合は、@changeではなく@inputを使います。)

 

実行イメージ

プロジェクトをカレントフォルダにして「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

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

いい感じですねえ。

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

ではでは。

追記

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

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

f:id:arakan_no_boku:20190902202557p:plain

https://opendata.resas-portal.go.jp/