0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Vue2 × Vuetifyでテーブル表示を実装してみた(AWS DynamoDB、Lambda使用)

Posted at

はじめに

Vue2とVuetifyを使ってテーブル表示を実装してみました。
流れは以下の通りです。

  1. DynamoDBとVueプロジェクトの作成
  2. プロジェクトを作成するボタンとプロジェクトを表示するテーブルの配置
  3. プロジェクトを作成するボタンを押してポップアップ画面を表示
  4. ポップアップ画面のテキストフィールドとボタンの配置
  5. 作成ボタンを押すとDynamoDBにデータを追加するLambda関数1の作成
  6. 作成ボタンを押すとDynamoDBから情報を取得し一覧をテーブルに表示するprojects関数の作成

開発環境

  • Windows 11
  • Vue CLI 5.0.8
  • Vue 2.7.14
  • npm 6.14.14
  • Node.js 14.17.5

実装

DynamoDBとVueプロジェクトの作成

まず、今回の実装で使うDynamoDBとVueプロジェクトを作成します。

DynamoDBの設定は以下の通りです。
今回は、ProjectName(文字列)をパーティションキーとして使用します。
image.png

Vueアプリケーションの作成の流れは以下の通りです。

ターミナル
vue create フォルダ名(任意)

作成できたら、以下のコマンドを実行して、Vuetifyを追加します。

ターミナル
vue add vuetify

途中でプリセットの選択を聞かれるので、Default(recommended)を選択します。

今回は作成したプロジェクト内のHelloWorld.vueを編集する形で進めていきます。

プロジェクトを作成するボタンとプロジェクトを表示するテーブルの配置

続いて、プロジェクトを作成するボタンとプロジェクトを表示するテーブルを配置していきます。
見た目は以下の通りです。
screencapture-localhost-8080-2023-03-13-13_56_00.png

これにあたり、HelloWorld.vueを書き換えます。
v-btnタグでボタンを配置することができます。
v-data-tableタグでテーブルを配置することができます。
scriptタグ内のdataでテーブルのヘッダーと中身のプロパティを定義します。
今回はDynamoDBのパーティションキーがProjectNameなので、headersのtextとvalueをProjectNameにします。

HelloWorld.vue
<template>
  <div>
    <v-btn
        outlined
        class="ma-1"
        color="primary"
    >
      プロジェクトの作成
    </v-btn>
    <v-data-table :headers="headers" :items="items"></v-data-table>
  </div>
</template>

<script>

export default {
  data() {
    return {
      headers: [
        { text: 'ProjectName', value: 'ProjectName' },
      ],
      items: []
    };
  },
};
</script>

プロジェクトを作成するボタンを押してポップアップ画面を表示

続いて、プロジェクトを作成ボタンを押すと、ポップアップ画面が表示されるようにしていきます。
見た目は以下の通りです。
screencapture-localhost-8080-2023-03-13-14_01_15.png

HelloWorld.vueのプロジェクト作成ボタンの下にポップアップ画面を追加します。
ポップアップ画面はv-dialogタグで実装できます。
ポップアップ画面の表示・非表示を切り替えるために、scriptタグ内のdataにdialogを定義し、初期状態をfalseにします。
プロジェクト作成ボタンのv-btnタグの中に「@click="dialog=true"」を追加することでdialogがtrueになり、ポップアップ画面が表示されるという仕組みです。

HelloWorld.vue
<template>
  <div>
    <v-btn
        outlined
        class="ma-1"
        color="primary"
        @click="dialog=true"
    ><!--@click="dialog=true"を追加-->
      プロジェクトの作成
    </v-btn>

  <!--追加ここから-->
    <v-dialog 
      v-model="dialog" 
      width="400px"
    >
      <v-card
        width="400px"
        class="mx-auto"
        :loading=loading
      >
      <v-card-title>プロジェクト名を入力してください。</v-card-title>
      </v-card>
    </v-dialog>
  <!--追加ここまで-->

    <v-data-table :headers="headers" :items="items"></v-data-table>
  </div>
</template>

<script>

export default {
  data() {
    return {
      dialog:false, //追加
      headers: [
        { text: 'ProjectName', value: 'ProjectName' },
      ],
      items: []
    };
  },
};
</script>

ポップアップ画面のテキストフィールドとボタンの配置

続いて、ポップアップ画面のテキストフィールドとボタンを配置していきます。

以下のような見た目になりますが、現段階では、入力して作成ボタンを押してもテーブルには表示されません。
screencapture-localhost-8080-2023-03-13-14_03_08.png

HelloWorld.vueのv-dialogタグの中に、テキストフィールドとキャンセルボタン、作成ボタンを追加します。
v-text-fieldでテキストフィールドを追加できます。
テキストフィールドに入力した値を入れるために、scriptタグ内のdataにinputTextを定義し、v-text-fieldにバインドします。

HelloWorld.vue
<template>
  <div>
    <v-btn
        outlined
        class="ma-1"
        color="primary"
        @click="dialog=true"
    >
      プロジェクトの作成
    </v-btn>
    <v-dialog 
      v-model="dialog" 
      width="400px"
    >
      <v-card
        width="400px"
        class="mx-auto"
        :loading=loading
      >
      <v-card-title>プロジェクト名を入力してください。</v-card-title>

        <!--追加ここから-->
        <v-card
         width="320px"
         class="mx-auto"
        >
          <v-text-field 
            v-model="inputText"
            outlined
            hide-details="true"
          ></v-text-field>
        </v-card>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn class="ma-2"   @click="dialog=false"
          >キャンセル
        </v-btn>
        <v-btn color="primary"
        >作成
        </v-btn>
        <v-spacer></v-spacer>
      </v-card-actions>
      <!--追加ここまで-->

      </v-card>
    </v-dialog>
    <v-data-table :headers="headers" :items="items"></v-data-table>
  </div>
</template>

<script>

export default {
  data() {
    return {
      dialog:false,
      inputText: '', //追加
      headers: [
        { text: 'ProjectName', value: 'ProjectName' },
      ],
      items: []
    };
  },
};
</script>

作成ボタンを押すとDynamoDBにデータを追加するLambda関数「create-project」の作成

続いて、作成ボタンを押すと、DynamoDBにデータを追加するcreate-project関数を作成します。
基本的な情報は以下の通りです。
image.png

関数の作成ボタンを押したら、追加の設定をしていきます。
基本設定でタイムアウトを30秒に変更してください。
スクリーンショット 2023-03-11 13.03.56.png

既存のロールにアクセスし、AmazonDynamoDBFullAccessにチェックを入れます。
image.png

今回はLambda関数単体のURLを用いるので、関数URLを作成します。
image.png

関数URLの設定は以下の通りです。
image.png

create-project関数のlambda_function.pyを以下のようにします。
先ほどHelloWorld.vueで定義したinput_textが送られてくるので、その中身をDynamoDBのProjectNameに追加するという処理です。

lambda_function.py
import boto3
import json

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('t-tsuchiyama-test')

def lambda_handler(event, context):
    input_text = json.loads(event['body'])['input_text']
    table.put_item(Item={
        'ProjectName': input_text,
    })
    return {
        'statusCode': 200,
        'body': json.dumps('OK'),
    }

HelloWorld.vueではcreate-project関数にinput_textの中身を送る関数postDataを追加します。
POSTされたら、dialogをfalseにして、ポップアップ画面を閉じます。

HelloWorld.vue
<template>
  <div>
    <v-btn
        outlined
        class="ma-1"
        color="primary"
        @click="dialog=true"
    >
      プロジェクトの作成
    </v-btn>
    <v-dialog 
      v-model="dialog" 
      width="400px"
    >
      <v-card
        width="400px"
        class="mx-auto"
      >
      <v-card-title>プロジェクト名を入力してください。</v-card-title>
        <v-card
         width="320px"
         class="mx-auto"
        >
          <v-text-field 
            v-model="inputText"
            outlined
            hide-details="true"
          ></v-text-field>
        </v-card>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn class="ma-2"   @click="dialog=false"
          >キャンセル
        </v-btn>
        <v-btn color="primary" @click="postData"
          >作成
        </v-btn>
        <v-spacer></v-spacer>
      </v-card-actions>
      </v-card>
    </v-dialog>
    <v-data-table :headers="headers" :items="items"></v-data-table>
  </div>
</template>

<script>
import axios from 'axios'; //追加

export default {
  data() {
    return {
      dialog:false,
      inputText: '',
      headers: [
        { text: 'ProjectName', value: 'ProjectName' },
      ],
      items: []
    };
  },
 //methods追加
  methods: {
    postData() {
      axios.post('create-project関数のURL', {input_text: this.inputText})
        .then(response => {
          console.log(response);
          this.dialog = false;
        })
        .catch(error => {
          console.error(error);
        });
    },
};
</script>

ここまで終えると、以下のようになります。

「a」というプロジェクト名を入力して作成ボタンを押します。
screencapture-localhost-8080-2023-03-13-14_09_39.png

DynamoDBに追加されていることが確認できます。
スクリーンショット 2023-03-13 11.03.05.png

作成ボタンを押すとDynamoDBから情報を取得し一覧をテーブルに表示するprojects関数の作成

続いて、作成ボタンを押すとDynamoDBから情報を取得し一覧をテーブル表示するprojects関数を作成します。
先ほどのcreate-project関数を作成した手順と同様に、projects関数を作成し、関数URLの設定まで行ってください。

関数URLまでの設定が終わったら、projects関数のlambda_function.pyを以下のようにします。
DynamoDBのテーブルをスキャンし中身を取得する処理です。

lambda_function.py
import boto3
import json

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('t-tsuchiyama-test')

def lambda_handler(event, context):
    response = table.scan()
    items = response['Items']
    return {
        'statusCode': 200,
        'body': json.dumps(items)
    }

HelloWorld.vueでは、作成ボタンを押してDynamoDBにProjectNameが追加された後に、DynamoDBの情報を取得してテーブルに表示させる関数getItemsを追加します。
また、createdの中身にもgetItemsを記述することで、作成ボタンを押した後だけでなく、ページをリロードしたタイミングでもテーブルが表示されます。
createdはページを表示するときとリロードするときに実行されます。

HelloWorld.vue
<template>
  <div>
    <v-btn
        outlined
        class="ma-1"
        color="primary"
        @click="dialog=true"
    >
      プロジェクトの作成
    </v-btn>
    <v-dialog 
      v-model="dialog" 
      width="400px"
    >
      <v-card
        width="400px"
        class="mx-auto"
      >
      <v-card-title>プロジェクト名を入力してください。</v-card-title>
        <v-card
         width="320px"
         class="mx-auto"
        >
          <v-text-field 
            v-model="inputText"
            outlined
            hide-details="true"
          ></v-text-field>
        </v-card>
      <v-card-actions>
        <v-spacer></v-spacer>
        <v-btn class="ma-2"   @click="dialog=false"
          >キャンセル
        </v-btn>
        <v-btn color="primary" @click="postData"
          >作成
        </v-btn>
        <v-spacer></v-spacer>
      </v-card-actions>
      </v-card>
    </v-dialog>
    <v-data-table :headers="headers" :items="items"></v-data-table>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      dialog:false,
      inputText: '',
      headers: [
        { text: 'ProjectName', value: 'ProjectName' },
      ],
      items: []
    };
  },
  //created追加
  created() {
    this.getItems();
  },
  methods: {
    postData() {
      this.loading = true;
      axios.post('create-project関数のURL', {input_text: this.inputText})
        .then(response => {
          console.log(response);
          this.dialog = false;
          this.getItems(); //追加
        })
        .catch(error => {
          console.error(error);
        });
    },
    //getItems追加
    async getItems() {
      try {
        const response = await axios.get('projects関数のURL')
        this.items = response.data
      } catch (error) {
        console.log(error)
      }
    }
  },
};
</script>

ここまで終え、新たに「b」、「c」というプロジェクトを作成すると以下のようになります。
screencapture-localhost-8080-2023-03-13-14_13_51.png

これでVue2とVuetifyを使ってテーブル表示を実装することができました。

おわりに

今回はVue2とVuetifyを使ってテーブル表示を実装してみました。
入力した値をテーブルに追加するというケースはよくあると思うので、ぜひ試してみてください。

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?