Laravel+Vue/Vuetify 編集機能を追加

前回までで登録・一覧・削除ができたので今回は編集機能を作ります。
Actionsのペンアイコンをクリックしたときに該当データの編集画面を表示しデータの変更ができるようにします。すでに登録用のコンポーネントにフォームがあるので共有化しましょう。

開発環境

Laradock v10
Laravel 7
Vue 2.6

Laravel:コントローラーにメソッド実装

showメソッドで指定されたIDのデータを返します。
updateメソッドで指定されたIDのデータを更新します。

    public function show($id)
    {
        $status = 200;
        $message = null;

        $data = null;
        $item = Item::find($id);
        if ($item) {
            $data = $item;
            $data['checkbox'] = explode(',', $data['checkbox']);
        } else {
            $status = 404;
            $message = 'Not Found.';
        }

        return response()->json(['item' => $data, 'status' => $status, 'message' => $message]);
    }

    public function update(ItemRequest $request, $id)
    {
        $status = 200;
        $message = null;
        $result = false;

        $data = $request->all();
        $data['checkbox'] = implode(',', $data['checkbox']);
        $item = Item::find($id);
        if ($item) {
            $result = $item->fill($data)->save();
        } else {
            $status = 404;
            $message = 'Not Found.';
        }

        return response()->json(['result' => $result, 'status' => $status, 'message' => $message]);
    }

※updateメソッドのリクエストは登録で使用したItemRequestを利用してバリデーションに対応します。
※Laravel側でエラーを出すとJavascriptが止まってしまうのでエラーとして返してJavascript側で処理することにします。

コンポーネント名を変更

フォームのコンポーネントはItemAddComponent.vueになっていましたが、共有化するためにitemEditComponet.vueに変更しましょう。

resources/js/components/User/ItemAddComponent.vue
↓
resources/js/components/User/ItemEditComponent.vue

Vue-Routerの変更

フォームの共有化のため、Vue-Routerの設定を変更します。

// import UserItemAdd from './components/User/ItemAddComponent'
import UserItemEdit from './components/User/ItemEditComponent'	// 変更

・・・

//        {
//            path: '/user/item/add',
//            name: 'user-item-add',
//            component: UserItemAdd,
//        },
        // 上記コードを以下に変更
        {
            path: '/user/item/edit/:id(\\d+)?',
            name: 'user-item-edit',
            component: UserItemEdit,
        },

※id付きでアクセスされたときはそのidでデータを呼び出して編集フォームに、idが無かったときは登録フォームにしたいと思います。

ItemComponentのリンク先変更

新規登録ボタンのリンク先変更

idを指定しない形で/user/item/editへ!

  <router-link to="/user/item/add">
    <v-btn>新規登録</v-btn>
  </router-link>
↓
  <router-link to="/user/item/edit">
    <v-btn>新規登録</v-btn>
  </router-link>

ペンアイコンを編集画面へのリンクに

上記、router.jsの設定により、router-linkでnameをuser-item-edit、paramにidを与えることで/user/item/edit/{id}にリンクしてくれます。

      <v-icon
        class="mr-2"
        @click="editItem(item)"
      >
        mdi-pencil
      </v-icon>
↓
      <router-link :to="{ name: 'user-item-edit', params: { id: item.id } }">
        <v-icon
          class="mr-2"
        >
          mdi-pencil
        </v-icon>
      </router-link>

ItemEditComponentの修正

ItemAddComponent.vueから名前を変更してItemEditComponent.vueにしたので内容を修正します。
resources/js/components/User/ItemEditComponent.vueの変更です。

タイトルの変更

v-ifを使ってforms.idの有無でタイトルの切り替え

  <h1>UserItemAdd</h1>
  ↓
  <h1 v-if="forms.id == ''">UserItemAdd</h1>
  <h1 v-else>UserItemEdit</h1>

formsにid追加

dataオブジェクトformsにidを追加します。

<script>
  export default {
    data() {
      return {
・・・
        forms: {
          id: '',			// 追加
          textbox: '',
          textarea: '',
          radiobtn: '1',
          select: '',
          checkbox: [],
        },
・・・

created()でItemデータ取得

ItemComponent.vueのリンクでparamを設定しましたが this.$route.params.id で取得することができます。これを利用してidが存在するときだけAxiosでItemデータを取得してformsに設定します。

     created() {
     ・・・
     // 以下追加
      if (this.$route.params.id) {
        this.forms.id = this.$route.params.id;
        axios.get('/ajax/user/item/' + this.$route.params.id).then((res) => {
          if (res.data.status == 200) {
            const item = res.data.item;
            item.radiobtn = item.radiobtn.toString()
            item.select = item.select.toString()
            this.forms = item;
          } else {
            // エラー処理
          }
        })
        .catch(function(error) {
          console.log(error)
          // エラー処理
        })
      }

※ここまでで編集フォームに変更するItemデータを設定するところまでできました。

methodsのsubmit()での送信先切り替え

送信ボタンを押したときの送信先もAxiosのメソッドの切り替えが必要です。
forms.idが空でなければ更新なので
putメソッドで送信先は/ajax/user/item/[変更するデータのID]
空なら登録で
postメソッドで送信先は/ajax/user/item
ですね。

        // 送信処理
        let ajax;
        if (this.forms.id) {
          // 更新
          ajax = axios.put('/ajax/user/item/' + this.forms.id, this.forms);
        } else {
          // 新規登録
          ajax = axios.post('/ajax/user/item', this.forms);
        }
        ajax.then((res) => {
        ・・・

後記

当初、編集機能まで書くつもりがなかったのですが、一応完結するために追加しました。
最初から登録と編集のフォームを共有化しておけばよかったですね。

編集完了時の戻り先(ページ)とかエラー時の対応とか実装できてないところがありますが、またいずれ・・・