トップイメージ

非同期通信でレコード作成・更新

前回の続きでvuetifyのdata-tableを使って、ユーザー管理画面を作成してみました。

今回は、このユーザー管理画面から非同期通信でデータを飛ばし、レコードを更新・作成できるようにしました。

なお、今回はnew edit のように更新と新規作成でページを分けたりせず、この一覧画面上でモデルのレコード生成・更新を同じ操作でできるようにしています。

管理画面イメージ

管理画面イメージ1

ソースコード

まずは、サーバーサイドのRails側のコードです。 Postをするため、ルーターとコントローラーを書き換えます。

#routes.rb

resources:users, :only => [:index,:create] do 
    collection do
      get 'search'
    end
  end

#user.controller.rb


def create
    #投稿されたものが新規かどうか判別
    user = User.find_or_initialize_by(id:user_params[:id])
    #idでレコードが見つからなければ、新規作成
    if user.new_record?
      user = User.new(user_params)
      user.save!
    #idでレコードが見つかれば、更新
    else
      user.update(user_params)
    end
    search()
  end

#非同期通信(axiosやajax)でユーザーの一覧データを返す
def search
    users = User.all.order(id:'desc')
    render json:{total:users.size,data:users}
  end

#ストロングパラメーター
private

  def user_params
    params.require(:user).permit(:id,:name,:name_kana,:syozoku,:seinen_ymd)
  end

次にvue側のコードです。 今回は前回掲載している、データグリッド部分はカットしています。

<template>
<v-app>
    <v-container>
    <!-- Userのデータテーブル -->
    <v-layout class="table" row wrap>
        <v-flex xs6>
            <grid
            :headers="headers"
            :contents="users"
            @grid_tr_click="InputForm"
            >
            </grid>
        </v-flex>   
        <v-flex xs5 class="ml-5">
          <template>
              <v-text-field
                label="ID"
                value=""
                hint="ユーザーID"
                id="user_id"
                v-model="id"
                prepend-icon="person"
              >
              </v-text-field>
              <v-text-field
                label="氏名"
                value=""
                hint="ユーザー氏名"
                id="user_simei"
                v-model="simei"
                prepend-icon="domain"
              >
              </v-text-field>
              <v-text-field
                label="氏名かな"
                value=""
                hint="ユーザー氏名かな"
                id="user_simei_kana"
                v-model="simei_kana"
                prepend-icon="domain"
              >
              </v-text-field>
              <v-text-field
                label="所属"
                value=""
                hint="所属情報"
                id="user_syozoku"
                v-model="syozoku"
                prepend-icon="group"
              >
              </v-text-field>              
               <v-menu
                  v-model="menu2"
                  :close-on-content-click="false"
                  :nudge-right="40"
                  lazy
                  transition="scale-transition"
                  offset-y
                  full-width
                  min-width="290px"
                >
               <template v-slot:activator="{ on }">
                <v-text-field
                  v-model="seinen_ymd"
                  label="生年月日"
                  prepend-icon="event"
                  v-on="on"
                  id="seinen_ymd"
                ></v-text-field>
              </template>
              <v-date-picker v-model="seinen_ymd" @input="menu2 = false"></v-date-picker>
               </v-menu>

              <v-layout justify-end>
                <v-btn color="success" v-on:click="hozon">保存</v-btn>
                <v-btn color="error">clear</v-btn>
              </v-layout>
          </template>
        </v-flex>
    </v-layout>
  </v-container>
</v-app>
</template>


<style scoped>

</style>

<script>
import Axios from 'axios'
import Grid from '../base_conponent/grid.vue'
import Datepicker from 'vuejs-datepicker';

export default{
  components: {
    "grid":Grid,
    "date-pciker":Datepicker
  },
  data () {
    return {
      //グリッドに詰めるデータ用の変数
      users:[],
      //(中略)
      //グリッド右のテキストボックスにデータを詰めるため
      id:"",
      simei:"",
      simei_kana:"",
      syozoku:"",
      //date-picker用
      seinen_ymd: "",
      menu2: false
    }
  },
  mounted(){
      let self = this;
      //data-table用のデータをrailsサーバーから取得
      Axios.get('/users/search')
        .then((res) => {
            self.users = res.data.data;
        })
        .catch(error => {
          alert("データ取得失敗");
        })
  },
  methods:{
    //左側のテーブルの列選択時に右側のフォームへデータを飛ばす(不要な改行・空行は削除)
    InputForm:function(data){
      this.id = data.currentTarget.cells[0].innerHTML.replace(/ /g, '').replace(/\r?\n/g,"");
      this.simei = data.currentTarget.cells[1].innerHTML.replace(/ /g, '').replace(/\r?\n/g,"");
      this.simei_kana = data.currentTarget.cells[2].innerHTML.replace(/ /g, '').replace(/\r?\n/g,"");
      this.syozoku = data.currentTarget.cells[3].innerHTML.replace(/ /g, '').replace(/\r?\n/g,"");
    },
    hozon:function(data){
          var yesNo = confirm("保存します。よろしいですか?")
          if (yesNo){
              //Userモデルへの保存処理
              const token = document.getElementsByName("csrf-token")[0].getAttribute("content");
              Axios.defaults.headers.common["X-CSRF-Token"] = token;
              Axios.post('/users/' ,{
                user:{
                  id:this.id,
                  name:this.simei,
                  name_kana:this.simei_kana,
                  syozoku:this.syozoku,
                  seinen_ymd:this.seinen_ymd.replace(/[^0-9]/g, '')
                }
              })
              .then((res) => {
                  alert('保存成功')
                  this.users = res.data.data
              })
              .catch(error => {
                  console.log(error)
              });
          }
      }
  }
  
}
</script>

これまでの整理

これで、vueとRailsで連携し、Userモデルをページ遷移なしで、生成・更新できるようになりました。

次回はレコード削除用のロジックを記載し、また入力フォームにバリデーションを付与し、意図しない入力をできないようにしていきたいと思います。