0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravel × Vue(Inertia.js)で家計簿アプリ作成【DBデータ表示・削除・トースト通知の実装まとめ】

Posted at

はじめに

この記事は、Laravel + Vue + Inertia.jsを使って家計簿アプリを作成する過程で学んだことをまとめた備忘録です。

  • データベースから取得したデータの表示
  • 削除機能(ボタンコンポーネント化)
  • SweetArler2を使った確認ダイアログとトースト通知
    といった、フロントとバックエンドの連携方法について解説します。

データベースの内容を画面に表示する

Dashboard.vue
Inertia経由で取得した支出データ(expenses)を一覧表示。フォームで新規登録もできます。

<script setup>
import { Head, useForm } from '@inertiajs/vue3';
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';
import InputLabel from '@/Components/InputLabel.vue';
import TextInput from '@/Components/TextInput.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import InputError from '@/Components/InputError.vue';

const props = defineProps({ expenses: Array });

const form = useForm({
  amount: '',
  date: '',
  title: '',
  category: '',
});

const submit = () => {
  form.post(route('expenses.store'), {
    onSuccess: () => form.reset(),
  });
};
</script>

<template>
  <AuthenticatedLayout>
    <!-- フォーム -->
    <form @submit.prevent="submit">
      <!-- 各入力欄 -->
      <!-- ...省略... -->
      <PrimaryButton class="mt-4">登録</PrimaryButton>
    </form>

    <!-- 一覧表示 -->
    <table>
      <thead>
        <tr>
          <th>日付</th><th>金額</th><th>費用名</th><th>カテゴリー</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="expense in expenses" :key="expense.id">
          <td>{{ expense.date }}</td>
          <td>{{ expense.amount }}</td>
          <td>{{ expense.title }}</td>
          <td>{{ expense.category }}</td>
        </tr>
      </tbody>
    </table>
  </AuthenticatedLayout>
</template>

削除機能の実装(コンポーネント化)

1. ルート設定(web.php)

Route::middleware(['auth'])->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
    Route::post('/expenses', [DashboardController::class, 'store'])->name('expenses.store');
    Route::delete('/expenses/{expense}', [DashboardController::class, 'destroy'])->name('expenses.destroy');
});

2. コントローラーに削除処理追加

public function destroy(Expense $expense)
{
    if(auth()->id() !== $expense->user_id) {
        abort(403);
    }
    $expense->delete();

    return redirect()->route('dashboard')->with('message', '削除しました');
}

3. 削除ボタンコンポーネントを作成

resources/js/Components/DeleteButton.vue

<script setup>
import { router } from '@inertiajs/vue3';

const props = defineProps({ expenseId: Number });

const destroy = () => {
  if (confirm('本当に削除しますか?')) {
    router.delete(route('expenses.destroy', props.expenseId), {
      onSuccess: () => router.reload(),
    });
  }
};
</script>

<template>
  <button @click="destroy" class="bg-red-500 text-white px-4 py-2 rounded hover:bg-red-600">
    削除
  </button>
</template>

4. Dashboard.vueで使用

<script setup>
import DeleteButton from '@/Components/DeleteButton.vue';
</script>

<!-- 表示部分 -->
<tr v-for="expense in expenses" :key="expense.id">
  <td>{{ expense.date }}</td>
  <td>{{ expense.amount }}</td>
  <td>{{ expense.title }}</td>
  <td>{{ expense.category }}</td>
  <td><DeleteButton :expense-id="expense.id" /></td>
</tr>

SweetAlert2の導入&削除時確認ダイアログ

1. インストール

npm install sweetalert2
# Laravel Sailの場合:
./vendor/bin/sail npm install sweetalert2

2. DeleteButton.vueに組み込み

<script setup>
import { router } from '@inertiajs/vue3';
import Swal from 'sweetalert2';

const props = defineProps({ expenseId: Number });

const destroy = () => {
  Swal.fire({
    title: '本当に削除しますか?',
    text: 'この操作は取り消せません!',
    icon: 'warning',
    showCancelButton: true,
    confirmButtonColor: '#d33',
    cancelButtonColor: '#3085d6',
    confirmButtonText: '削除する',
    cancelButtonText: 'キャンセル',
  }).then((result) => {
    if (result.isConfirmed) {
      router.delete(route('expenses.destroy', props.expenseId), {
        onSuccess: () => {
          router.reload();
          Swal.fire('削除しました', 'データは正常に削除されました。', 'success');
        },
      });
    }
  });
};
</script>

SweerAlert2でトースト通知(登録完了メッセージなど)

1. Controllerでフラッシュメッセージを設定

return redirect()->route('dashboard')->with('message', '登録しました');

2. HandleInertiaRequests.phpで共有

public function share(Request $request): array
{
    return array_merge(parent::share($request), [
        'flash' => [
            'message' => fn () => $request->session()->get('message'),
        ],
    ]);
}

3. Dashboard.vueでトースト表示

<script setup>
import Swal from 'sweetalert2';
import { usePage } from '@inertiajs/vue3';
import { watch } from 'vue';

const page = usePage();

watch(() => page.props.flash?.message, (message) => {
  if (message) {
    Swal.fire({
      toast: true,
      position: 'top-end',
      icon: 'success',
      title: message,
      showConfirmButton: false,
      timer: 2000,
      timerProgressBar: true,
    });
  }
});
</script>

おわりに

  • データベースの保存
  • 削除処理(確認つき・非同期)
  • トースト通知の実装
    以上の内容を通して、Inertia.js + Vue.js + Laravelの連携方法が少しでも理解できたなら幸いです。
0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?