サーバーレスWebアプリにメールフォームを追加実装する 〜 フロントエンド編 〜

# サーバーレスWebアプリにメールフォームを追加実装する 〜 フロントエンド編 〜

## はじめに
[AWSを活用したサーバーレスWebアプリの制作](https://qiita.com/w2or3w/items/87b57dfdbcf218de91e2)で作ったWebアプリにメールフォームを追加実装します。
フロントエンド・バックエンドの2部構成にしています。
バックエンド編はこちら。
[サーバーレスWebアプリにメールフォームを追加実装する 〜 バックエンド編 〜](https://qiita.com/w2or3w/items/4ed298b969b9ddc9c5a3)

## フロントエンド
Vue.jsのWebアプリにメールフォーム用のページを追加します。

### VeeValidateの利用
メールフォームの各入力値チェックのために、VeeValidateというものを利用しました。
VeeValidateとは、Vue.js用のバリデーションコンポーネントライブラリです。

利用するために、まずはVeeValidateをプロジェクトにインストールする必要があります。

```
npm i vee-validate
```

使い方などの詳細は以下のページを参照してください。
https://logaretm.github.io/vee-validate/overview.html#getting-started

### コンポーネントの実装
VeeValidateを利用してバリデーションを効かせたメールフォーム画面のコンポーネントを実装します。
デザインコンポーネントは例によってVuetifyを利用しています。
必要な入力項目をすべて適切に入力しないとSUBMITボタンが有効にならないようにバリデーションを効かせ、ただ、SUBMITボタンを押下しても入力内容をアラートするだけにしておきます。(バックエンドの呼び出しは後で実装します。)

```src/components/Mail.vue
<template>
  <v-container>
    <p>Mail Form</p>

    <ValidationObserver ref="observer" v-slot="{ validate, reset, invalid }">
      <ValidationProvider v-slot="{ errors }" name="name" rules="required|max:25">
        <v-text-field
          label="Name"
          v-model="name"
          :counter="25"
          :error-messages="errors"
          required
        ></v-text-field>
      </ValidationProvider>
      
      <ValidationProvider v-slot="{ errors }" name="email" rules="required|email">
        <v-text-field
          label="E-mail"
          v-model="email"
          :error-messages="errors"
          required
        ></v-text-field>
      </ValidationProvider>
      
      <ValidationProvider v-slot="{ errors }" name="contens" rules="required|max:300">
        <v-textarea
          label="Message"
          v-model="message"
          :error-messages="errors"
          :counter="300"
          rows="8"
          required
        ></v-textarea>
      </ValidationProvider>

      <v-btn @click="onSubmit" :disabled="invalid">submit</v-btn>
      <v-btn @click="onValidate">validate</v-btn>
      <v-btn @click="onClear">clear</v-btn>
    </ValidationObserver>
    
  </v-container>
</template>

<script>
import { required, email, max } from "vee-validate/dist/rules"
import { extend, ValidationObserver, ValidationProvider, setInteractionMode } from "vee-validate"

setInteractionMode("eager");

extend("required", {
  ...required,
  message: "{_field_} can not be empty",
});

extend("max", {
  ...max,
  message: "{_field_} may not be greater than {length} characters",
});

extend("email", {
  ...email,
  message: "Email must be valid",
});

export default {
  name: "Mail",

  components: {
    ValidationProvider,
    ValidationObserver,
  },
  
  data: () => ({
    name: "", 
    email: "", 
    message: "", 
  }), 
  
  methods:{
    async onSubmit(){
      alert(this.name + " / " + this.email + " / " + this.message);
    }, 
    onValidate(){
      this.$refs.observer.validate();      
    }, 
    onClear(){
      this.name = "";
      this.email = "";
      this.message = "";
      this.$refs.observer.reset();
    }
  }
}
</script>
```

### 実行結果
![Screenshot 2020-03-29 at 08.05.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/92c575e7-d295-6987-5425-076b2f54c91c.png)

## バックエンド
[バックエンド編](https://qiita.com/w2or3w/items/4ed298b969b9ddc9c5a3)へ記載しています。
終わったら戻ってきてください。

## フロントエンドからAppSyncの呼び出し
バックエンドが済んだら、最後にWebアプリからの呼び出しです。
バックエンド編でAppSyncに追加したIF(processSendMail)をWebアプリからリクエストします。

```src/graphql/mutations.js
export const processSendMail = `
    mutation processSendMail($input: ProcessSendMailInput!) {
        processSendMail(input: $input) {
            statusCode
            body
        }
    }
`;
```

```src/components/Mail.vue
 :
<script>
import { required, email, max } from "vee-validate/dist/rules"
import { extend, ValidationObserver, ValidationProvider, setInteractionMode } from "vee-validate"
import { Auth, API, graphqlOperation } from 'aws-amplify';
import { processSendMail } from "../graphql/mutations";
 :
  methods:{
    async onSubmit() {
      let apiResult = await API.graphql(graphqlOperation(processSendMail, 
        {input : {name: this.name, email: this.email, message: this.message}})
      ).catch(error => {
        console.error(error);
      });
    }, 
```

実行して、フォームに入力し、SUBMITボタン押下によりメールが届くことを確認してください。

## あとがき
[バックエンド編](https://qiita.com/w2or3w/items/4ed298b969b9ddc9c5a3#%E3%81%82%E3%81%A8%E3%81%8C%E3%81%8D)へまとめて書きます。