GASでWebアプリ｢映画鑑賞記録｣を作る⑪ ／ Vue.js用のセレクトボックス「vue-select」を使用する

# 今回やること
　ダイアログボックスの「映画館」の入力項目を、プルダウンリストに変更します。
　プルダウンリストに表示するデータは、スプレッドシートの［映画館］シートを使用します。
　また、プルダウンリストについては、**Vue.js** に対応した高機能な部品（「**vue-select**」）がありましたので、これを使用します。
　　◆参考サイト [高機能なセレクトボックス「vue-select」の使い方](https://www.kabanoki.net/3786/)

　「鑑賞種別」については、［映画館］シートのデータを利用して自動更新する様に変更します。
　これに伴って、ダイアログボックスの「鑑賞種別」を削除します。

# 「vue-select」の導入
#### Index.html
　ライブラリをCDNで取得します。

```html
  <!-- vue-select -->
  <script src="https://unpkg.com/vue-select@latest"></script> 
  <link rel="stylesheet" href="https://unpkg.com/vue-select@latest/dist/vue-select.css">
```

#### javascript.html
　ライブラリを呼び出します。

```html
<script>
  const vueSelect = VueSelect.VueSelect;
    ：
</script>
```

#### Vuejs.html
　子コンポーネント（ダイアログボックス）の`components`に、`'vue-select': vueSelect`を追加します。

```javascript
Vue.component("modal", {
    ：
  components: {
    'vuejs-datepicker': vuejsDatepicker,
    'vue-select': vueSelect
  }
});
```

# ダイアログボックスの「映画館」と「鑑賞種別」を変更
#### modalScript.html
　「映画館」の`<input>`タグを削除して、`<vue-select>`タグを追加します。
　プルダウンリストに表示するデータを、`:options="vueselect.options"`で参照します。（下記の **Vuejs.html** を参照）
　プルダウンリストで選択された値を、`v-model="cond.theaterName"`で格納します。（初期値の設定も同様）

　「鑑賞種別」（全体、`<div class="form-group">`タグから全て）を削除します。

```html
  <transition name="modal">
    ：
              <div class="form-group">
                <label for="theater-name" class="col-form-label">映画館：</label>
                <!-- <input type="text" class="form-control" id="theater-name" v-model="cond.theaterName"> -->
                <vue-select id="theater-name" :options="vueselect.options" v-model="cond.theaterName"></vue-select>
              </div>
                ：
         <!-- <div class="form-group">
              <div class="input-group">
                <label for="viewing-type" class="col-form-label">鑑賞種別：</label>
                <input type="text" class="form-control" id="viewing-type" v-model="cond.viewingType">
              </div>
              </div> -->
            </form>
          </div>
    ：
  </transition>
</script>
```

#### Vuejs.html
　プルダウンリストの映画館名をセットする変数（`options: []`）を、子コンポーネント（ダイアログボックス）と親コンポーネントに追加します。
　`options: []`には、リストに表示する文字列を1次配列としてセットします。
　→ ex.`['川越スカラ座', '池袋シネマ・ロサ', '深谷シネマ',…]`

```javascript
Vue.component("modal", {
  template: "#modal-template",
  props: {
      ：
    vueselect: {
      options: [] 
    }
  },
    ：
});

var app = new Vue({
  el: '#app',
  data: {
      ：
    vueselect: {
      options: []
    }, 
    ：
});
```
#### Index.html
　**Vuejs.html** で追加した変数（`options: []`）を連携する為に、`<modal>`タグに`v-bind:vueselect="vueselect"`を追加します。

```html
    <modal v-if="showModal" v-on:close-modal="doHideModal" v-on:add-data="doAddData" v-bind:message="message" v-bind:subject="subject" v-bind:cond="cond" v-bind:datepicker="datepicker" v-bind:vueselect="vueselect">
      <h3 slot="header">custom header {{ processingType }}</h3>
    </modal>
```

# プログラム（処理）の変更
#### ViewingRecord.gas
　先ず、サーバ側の処理を変更します。

- `getTheaters(year)`　**※追加**
  - **処理概要**：［映画館］シート（スプレッドシート）から「映画館名」と「鑑賞種別」を取得する。
  - **引数**　　：`yeat`: 年を示す文字列。ex.`'2021年'`［映画館］シートは、年毎にファイルが分かれ    
　　　　　ている。
  - **返値**　　：「映画館名」と「鑑賞種別」を2次配列で返す。

```javascript
function getTheaters(year) {
  var fileId = getFileIdFromYearSettings(year);
  var sheet = SpreadsheetApp.openById(fileId).getSheetByName('映画館');
  var lastRow = sheet.getLastRow();
  var theaters = sheet.getRange(3, 3, (lastRow - 2), 2).getValues();  //［映画館］シートの「映画館名」列 と「鑑賞種別」列 を取得。

  return theaters;
}
```
- `getViewingType(theaterName, year)`　**※追加**
  - **処理概要**：「映画館名」から［映画館］シートを検索して該当する「鑑賞種別」を取得する。　　　　　
  - **引数**　　：`theaterName`:「映画館名」。    
　　　　　`year`: 年を示す文字列。ex.`'2021年'`［映画館］シートは、年毎にファイルが分かれ    
　　　　　ている。
  - **返値**　　：「鑑賞種別」。`1`:映画館, `2`:DVD, `3`:配信, `4`:テレビ, `9`:その他

```javascript
function getViewingType(theaterName, year) {
  var theaters = getTheaters(year);

  for(var i = 0; i < theaters.length; i++) {
    if(theaters[i][0] === theaterName) {
      return theaters[i][1];
    }
  }

  return false;
}
```
　`addData()`の［鑑賞履歴］シートにデータをセットする部分を修正します。
　「鑑賞種別」の値は、従来ダイアログボックスからの入力で設定していましたが、`getViewingType()`で取得した値を設定する様に変更します。

```javascript
function addData(cond) {
    ：
  //sheet.getRange(targetRow, 2, 1, 6).setValues([[cond.id, cond.viewingDate, cond.movieName, cond.firstLook, cond.viewingType, cond.theaterName]]);
  var viewingType = getViewingType(cond.theaterName, cond.year);
  sheet.getRange(targetRow, 2, 1, 6).setValues([[cond.id, cond.viewingDate, cond.movieName, cond.firstLook, viewingType, cond.theaterName]]);
}
```

#### javascript.html
　クライアント側の処理を変更します。

- `getTheaters(year)`　**※追加**
  - **処理概要**：サーバ側の`getTheaters()`の呼出し。    
　　　　　取得したデータ（「映画館名」「鑑賞種別」）から、プルダウンリスト用の配列を作成    
　　　　　する。
  - **引数**　　：`year`: 年を示す文字列。ex.`'2021年'`［映画館］シートは、年毎にファイルが分かれ    
　　　　　ている。

```javascript
  function getTheaters(year) {
    google.script.run.withSuccessHandler(
      function(v, element) {
        var theaters = [];
        for(let theater of v) {
          theaters.push(theater[0]);
        }
        app.vueselect.options = theaters;
      })
      .withFailureHandler(
        function(msg, element) {
          showError(msg);
        })
      .withUserObject(this)
      .getTheaters(year);
  }
```

#### Vuejs.html
　**Vue.js** の処理（クライアント側の処理）も変更します。
　`mounted:`（インスタンスがマウントされた後の処理）と`methods:`の`doChangeYear:`（どちらも処理の一番最後）に、`getTheaters()`（ **javascript.html** ）の呼出しを追加します。

```javascript
var app = new Vue({
  el: '#app',
    ：
  mounted: function() {
      ：
    getTheaters(this.selectedYear);
  },
  methods: {
      ：
    doChangeYear: function() {
        ：
      getTheaters(this.selectedYear);
    }
  }
});
```
# 結果
　〔記録追加〕ボタンをクリックすると、ダイアログボックスが表示されます。
　「映画館」がプルダウンリストに変更され「鑑賞種別」が削除されています。
![vue-select1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510221/5e29a8a1-5449-a749-7c81-459ade339b7f.png)
　「映画館」を選択すると、映画館名のリストが表示されます。
![vue-select2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510221/ad0e3f05-977d-3a43-106d-7088b8dcd76f.png)
　「映画館」に`新宿`と入力すると、リストの表示が絞り込まれます。
![vue-select3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510221/6ec2da5c-41d1-5936-1b4d-f16ac75b207e.png)

　一覧表の行をクリックする（更新）と、既に入力していた「映画館名」が正しく表示されます。
![vue-select4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510221/1f1a594d-a27b-b4a2-9357-3e3cd9899b37.png)

**◆前の記事** [GASでWebアプリ｢映画鑑賞記録｣を作る⑩](https://qiita.com/pump33/items/3d2f4504a73c95e00cd5)
**◆次の記事** [GASでWebアプリ｢映画鑑賞記録｣を作る⑫](https://qiita.com/pump33/items/240ce06996403361dda3)

**◆索引** [GASでWebアプリ｢映画鑑賞記録｣を作る《索引》](https://qiita.com/pump33/items/8ded0e6fd3c336e705f4)