ユーザーの入力に応じてリストの内容を書き換える。（Google Apps Script ＋ Vue.js ＋ Bootstrap）

# はじめに
部署リストと氏名リストを設置し、
選択された部署に紐づく氏名のみ抽出して氏名リストに表示させる。

## vue.html
部署のリストデータはスプレッドシートから読み込み[deptList]にセットし、
そのリストから選択された値を[sortUser]に格納する。

[watch]は,データ変更の検知して処理を実行するプロパティ。
そのプロパティに[sortUser]を指定して、
ユーザーが部署を選択した際にその選択した部署でユーザー情報をフィルタリングする。

```ruby:vue.html
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

<script>  
  var vm = new Vue({
    el: '#app',
    data: {
      changeTemplate:'applyDisp',
      deptList:[{}],
      userName:'',
      sortUser:'',
      userList:[{}],
      selectedUserList:[{}],
    },
    computed: {         
    },
    watch: {
      //sortUser値の変化をwatchして変化したら選択された値でリストをフィルターする
      sortUser: function (){
        var selDept = this.sortUser;
        this.selectedUserList = this.userList.filter(function(el,index){
          if (el.Dept == selDept) return true;
        });
      }
    },
    methods:{
      setDeptList: function(deptData){
        this.deptList = deptData;
      },
      setUserList: function(userData){
        this.userList = userData;
      },
      checkForm: function(){
        this.changeTemplate = 'confirmDisp';
      },
      appendData: function(){
        this.changeTemplate = 'thanksDisp';
      },
    },
    created: function(){
      google.script.run
        .withSuccessHandler(this.setDeptList).getDeptList(); 
      google.script.run
        .withSuccessHandler(this.setUserList).getUserList();   
    },
  })
</script>
```

## index.html
```ruby:index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <?!= HtmlService.createHtmlOutputFromFile('css').getContent(); ?>

  </head>
  <body>

  <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>

  <div class="collapse navbar-collapse" id="navbarsExampleDefault">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Link</a>
      </li>
      <li class="nav-item">
        <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
      </li>
      <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="#" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>
        <div class="dropdown-menu" aria-labelledby="dropdown01">
          <a class="dropdown-item" href="#">Action</a>
          <a class="dropdown-item" href="#">Another action</a>
          <a class="dropdown-item" href="#">Something else here</a>
        </div>
      </li>
    </ul>
    <form class="form-inline my-2 my-lg-0">
      <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
      <button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
    </form>
  </div>
  </nav>

  <main role="main" class="container">

    <div class="starter-template">
      <h1>Bootstrap starter template</h1>
      <p class="lead">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p>
    </div><!-- /.starter-template -->

    <div id="app">
    
    <div class="form-group row"> 
    <label for="selectedDept" class="col-sm-2 col-form-label">Select Name</label>
      <div class="col-sm-5">
      <select id="sortUser" v-model="sortUser" class="form-control">
        <option v-for="option in deptList" v-bind:value="option.ID">
          {{ option.Name }}
        </option>
      </select>
      </div>
      <div class="col-sm-5">
      <select id="userName" v-model="userName" class="form-control">
        <option v-for="option2 in selectedUserList" v-bind:value="option2.ID">
          {{ option2.Name }}
        </option>
      </select>
      </div>
    </div>

    </div><!-- /.vue.el.app -->

  </main><!-- /.container -->

  <?!= HtmlService.createHtmlOutputFromFile('js').getContent(); ?>
  </body>
  <?!= HtmlService.createHtmlOutputFromFile('vue').getContent(); ?>
</html>
```

## コード.gs
```ruby:コード.gs
function doGet() {
  var html = HtmlService.createTemplateFromFile("index").evaluate().addMetaTag('viewport','width=device-width,initial-scale=1,minimal-ui');
  return html;
}

function getSS(spreadSheetID, sheetName){

  var res = SpreadsheetApp.openById(spreadSheetID)
    .getSheetByName(sheetName).getDataRange().getDisplayValues();
  
  var keys = res.splice(0, 1)[0];
  
  return value = res.map(function(row) {
    var obj = {}
    row.map(function(item, index) {
      obj[keys[index]] = item;
    });
    return obj;
  });
}

function getDeptList() {
  
  var SSID = "yourSpreadsheetID";
  var SN = "yourSheetName";
  
  var res = getSS(SSID, SN);
  
  return res; 
}

function getUserList() {
  
  var SSID = "yourSpreadsheetID";
  var SN = "UserList";
  
  var res = getSS(SSID, SN);
  
  return res; 
}
```

## css.html
```ruby:css.html
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<style>
  body {
    padding-top: 5rem;
  }
  .starter-template {
    padding: 3rem 1.5rem;
    text-align: center;
  }     
  .bd-placeholder-img {
    font-size: 1.125rem;
    text-anchor: middle;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }
  @media (min-width: 768px) {
    .bd-placeholder-img-lg {
    font-size: 3.5rem;
     }
  }
</style>
```
## js.html
```ruby:js.html
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
```
# 参考
[Vue.js > 算出プロパティとウォッチャ > ウォッチャ](https://jp.vuejs.org/v2/guide/computed.html#%E3%82%A6%E3%82%A9%E3%83%83%E3%83%81%E3%83%A3)