6
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.

Vue3 + laravel10でSPA作成 ③詳細画面作成

Posted at

はじめに

本記事はVue3 + laravel10でSPA作成 ②DB連携の続きになります。
今回の目標は詳細画面の作成とボタンアクションの実装までとなります。

詳細画面作成

1.router.jsの編集

resources\js\router.jsを編集し、詳細画面のルーティングを追加します。

router.js

+ import detail from "../views/Detail.vue"

const routes = [
    {
        path: "/",
        component: home,
        name: "home"
    },
+    {
+        path: "/detail",
+        component: detail,
+        name: "detail"
+    },
]

2.詳細画面コンポーネントの作成

resources\views\Detail.vueを作成します。
style scopedにしていない理由は、Vuetifyが生成するhtmlに対してスタイルを適用したいためです。ただし他コンポーネントまでスタイル適用されるので、注意が必要です。

Detail.vue
<template>
    <v-container fluid>
        <h4 class="mb-5">ToDo詳細</h4>
        <div class="input-form">
            <v-row>
                <v-col cols="2" style="text-align: right; vertical-align: middle;">
                    タイトル:
                </v-col>
                <v-col cols="4">
                    <v-text-field density="compact" hide-details variant="solo"
                     class="inner-text" v-model="todoDetail.TODO_NAME"></v-text-field>
                </v-col>
            </v-row>
            <v-row>
                <v-col cols="2" style="text-align: right;">
                    ステータス:
                </v-col>
                <v-col cols="3">
                    <v-text-field density="compact" hide-details variant="solo"
                    class="inner-text" v-model="todoDetail.STATUS"></v-text-field>
                </v-col>
            </v-row>
        </div>
        <div class="mt-5">
            <v-row>
                <v-col cols="5">
                    <v-btn to="/" color="blue-grey-lighten-4">戻る</v-btn>
                </v-col>
                <v-col cols="2">
                    <v-btn v-if='props.todoId == null' @click="createTodo" color="blue-accent-2">新規作成</v-btn>
                    <v-btn v-else @click="updateTodo" color="blue-accent-2">更新</v-btn>
                </v-col>
            </v-row>
        </div>
    </v-container>
</template>

<script setup>
import { ref, onMounted } from 'vue'
// 前画面(ホームからToDoIDを受け取る)
const props = defineProps({
    todoId: String
})


// ToDoデータ取得
const todoDetail = ref({  TODO_NAME: "", STATUS: "", CREATE_DATE: ""})
if (props.todoId != null) {
    onMounted(async () => {
        var res = await axios.post('getTodo', props)
        if (res.data != undefined) {
            todoDetail.value = res.data[0]
        }

    })
}

// 更新
const updateTodo = async () => {
    // ToDo情報にIDを付ける
    todoDetail.TODO_ID = props.todoId
    await axios.post('updateTodo', todoDetail.value);
}

// 新規作成
const createTodo = async () => {
    await axios.post('createTodo', todoDetail.value)
}
</script>
<style>
.input-form {
    font-size: 14px;
}

.inner-text input {
    padding: 0px 2px 0px 2px;
    min-height: 20px;
    font-size: 10px !important;
}

</style>

3.詳細画面の画面モード

ホーム画面のボタン押下(「更新」,「新規作成」)によって表示を切り替えます。
「更新」ボタンの場合はtodoIdをパラメータとして送るので、詳細画面がパラメータを受け取れるように、resources\js\router.jsを編集します。

router.js
    {
-       path: "/detail",
+       path: "/detail/:todoId?",
        component: detail,
        name: "detail",
+       props: true
    },

「更新」押下の場合に、更新モードで詳細画面が表示されることを確認します。
image.png

4.api.phpの編集

取得、新規作成、更新のルーティングをroutes\api.phpに追加する。

api.php
+ Route::post('getTodo',[TodoController::class,'getTodo']);
+ Route::post('updateTodo',[TodoController::class,'updateTodo']);
+ Route::post('createTodo',[TodoController::class,'createTodo']);
+ Route::post('deleteTodo',[TodoController::class,'deleteTodo']);

5.コントローラの編集

+ use Illuminate\Http\Request;

    public function getTodoList()
    {
        $sql = 'SELECT * FROM TODO_LIST';
        $items = DB::select($sql);
        return $items;
    }

+    // 詳細更新モード起動時
+    public function getTodo(Request $req)
+    {
+        $todoId = $req->input('todoId');
+        $sql = 'SELECT * FROM TODO_LIST WHERE TODO_ID = :todoId';
+        $items = DB::select($sql, ['todoId' => $todoId]);
+        return $items;
+    }

+    // 新規作成
+    public function createTodo(Request $req)
+     {
+        $params = $req -> only(['TODO_NAME', 'STATUS']);
+        $sql = <<< 'SQL'
+        INSERT 
+        INTO todo_list(TODO_NAME, STATUS, CREATE_DATE) 
+        VALUES (:TODO_NAME, :STATUS, CURDATE())
+        SQL;
+        DB::insert($sql, $params);
+     }

+    // 更新
+    public function updateTodo(Request $req)
+    {
+        $params = $req -> only(['TODO_NAME', 'STATUS', 'TODO_ID']);
+        $sql = <<< 'SQL'
+        UPDATE todo_list 
+        SET
+            TODO_NAME = :TODO_NAME
+            , STATUS = :STATUS
+        WHERE
+            TODO_ID = :TODO_ID
+        SQL;
+        DB::update($sql, $params);
+    } 

+        // 削除
+    public function deleteTodo(Request $req)
+    {
+        $todoId = $req -> input('todoId');
+        $sql = 'DELETE FROM TODO_LIST WHERE TODO_ID = :todoId';
+        DB::delete($sql,['todoId' => $todoId]);
+    }

6.トップページの削除ボタン実装

resources\views\Home.vueを編集する。

-                            <v-btn @click="deleteTodo()" density="compact" color="red">削除</v-btn>
+                            <v-btn @click="deleteTodo(item.TODO_ID)" density="compact" color="red">削除</v-btn>
+ // 削除
+ const deleteTodo = async (todoId) => {
+     await axios.post('deleteTodo',  {todoId: todoId})
+     var res = await axios.get('getTodoList')
+     todoList.value = res.data
+ } 

確認

新規作成、更新についてはボタンを押下し、戻るを押してトップに戻り、内容が反映されているか確認、削除については押下直後に反映されることを確認する。

さいごに

最後までお読みいただきありがとうございました。
制作時の所感としては、Vuetify2,Vuetify3の情報の混在や、laravel10がまだまだネット記事が充実していないことなどから、環境構築、エラー解消に逐一ハマってしまうことが多かったです汗。
誤りのご指摘、よりよい方法、動作しない等のご意見あればコメントを頂ければと思います。

6
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
6
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?