Vue.js (+TypeScript) × microCMSでお問い合わせフォームを作成する

## 経緯

前記事（[ヘッドレスCMS × Static Site GeneratorでJamstackな爆速表示サイトを作ってみるチュートリアル](https://qiita.com/ohnaka0410/items/c2f6d7c90330c1d97c69)）で、
>できれば、(axiosとかで叩ける)お問い合わせ用APIとかあれば良いけど、なにか良いサービスないかな:thinking:

と書いたところ、早速

> こちらmicroCMSがPOSTに対応したのでお使いいただけるかと...！ぜひお試しください🙏
> 
> API経由でコンテンツを作成できるようになりました🌐
> https://microcms.io/blog/http_post_api/

とお知らせが！！

というわけで、勢いでお問い合わせフォームを実装してみます。
※今回は、とりあえずVueでローカルでサクッと試したのでJamstackではないです😇

## 実装

### 環境
```shell:Console
% node -v
v12.13.0
% npm -v
6.13.6
```

### プロジェクトの作成
Vue CLIを使ってお好みの設定でプロジェクトを作成します。

```shell:Console
% npx @vue/cli create vue-contact-demo

Vue CLI v4.2.2
? Please pick a preset: Manually select features
? Check the features needed for your project: TS, Linter
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? No
? Pick a linter / formatter config: Prettier
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)Lint o
n save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
```

### 開発サーバの起動
```shell:Console
% cd vue-contact-demo
% npm run serve
```
ブラウザで`http://localhost:8080/`へアクセスし表示確認を行います。
![127.0.0.1_8080_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/9948fdae-f862-cc72-46f1-58a0ded9e4fb.png)

### microCMSの設定
`X-WRITE-API-KEY` を発行します。
![jamstack-demo.microcms.io_settings_apikey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/02c48598-c4f5-2617-e6c2-42bd4b73c9fd.png)
![jamstack-demo.microcms.io_settings_apikey (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/ac252ee1-d9b6-b49b-4ed0-f03c9db5c0f2.png)

お問い合わせ登録用のエンドポイントを作成します。
![jamstack-demo.microcms.io_create-api.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/dabbf52c-1465-ed5a-ba49-653a1e3a86e1.png)

![jamstack-demo.microcms.io_create-api (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/01af538d-a10b-96d1-ee77-530a8490aef2.png)
※リスト形式じゃないと、POSTが利用できません。

![jamstack-demo.microcms.io_create-api (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/3418fffa-c63e-69b8-0d20-1eb9414883f3.png)

POSTメソッドを有効にします。
![jamstack-demo.microcms.io_create-api (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/0ba8f021-fd63-3493-0c41-ab3486e87cc7.png)

### フォームの作成
APIを呼び出すために、axiosを追加します。

```sh:Console
% npm i axios
% npm i -D @types/axios
```
フォームを実装します。

```vue:src/components/ContactForm.vue
<template>
  <form>
    <dl>
      <dt>名前</dt>
      <dd><input type="text" v-model="inputData.name"></dd>
      <dt>お問い合わせ内容</dt>
      <dd><textarea v-model="inputData.text"></textarea></dd>
    </dl>
    <button type="button" @click="send">送信</button>
  </form>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import axios from 'axios';

interface contactData {
  name:string
  text:string
}

@Component
export default class ContactForm extends Vue {
  /**
   * 入力データ
   */
  private inputData: contactData = {
    name: '',
    text: ''
  };
  /**
   * 送信処理
   */
  private async send(): Promise<void> {
    await axios.post(
      // url
      'https://jamstack-demo.microcms.io/api/v1/contact',
      // data
      this.inputData,
      // config
      {
        headers: {
          'Content-Type': 'application/json',
          'X-WRITE-API-KEY': '86f1db0b-f655-4568-b32f-f8be991f150f',
        },
      }
    );
  }
}
</script>
```
😇ざざっと作ってみただけなので、ちゃんと実装する場合は、しっかり設計、ファイル分割しましょう。

とりあえず、メインのコンポーネントに追加します。

```diff:src/App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png" />
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
+     <ContactForm />
  </div>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import HelloWorld from "./components/HelloWorld.vue";
+ import ContactForm from "./components/ContactForm.vue";

@Component({
  components: {
-     HelloWorld
+     HelloWorld,
+     ContactForm
  }
})
```
### 動作確認
ブラウザで`http://localhost:8080/`へアクセスし、フォームを投稿し、
microCMS側で投稿確認を行います。
![jamstack-demo.microcms.io_apis_contact.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242655/a964c08a-ea57-edd8-0c77-1ddc9ee16ace.png)


## まとめ
- ちょっとしたユーザ→運営のアクションであればアリかなと思います。
- microCMS側の設定で、コンテンツ投稿時（今回の場合は、お問い合わせがあった時）にslackやchatworkに投稿することができます。
- 実プロジェクトで導入する場合は、コンテンツの投入上限があるため、（最近よくある）画像認証などを使って、できるだけスパムとかは除きたいところ。。。。

以上です。