4
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 3 years have passed since last update.

Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part9 ~最終回~

Last updated at Posted at 2020-03-19

#前回のパート
前回はtodo削除機能の実装を行いました
今回は残す最後の機能として、todoの更新機能の実装をやっていきます
今回が最後のパートになります
前回のパートはこちら→Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part8

#Laravel側の実装
todoの更新に使うのはTodoController.phpupdate()アクションになります
update()アクションは/todo{id}に対してPUTリクエストで呼び出されます

それではTodoController.phpを開きupdate()アクションに下記を追加してください

TodoController.php
public function update(Request $request, $id)
{
    $todo = Todo::find($id);
    $todo->text = $request->text;
    $todo->save();

    return response('', 200);
}

引数の$idを受け取ってtodosテーブルからそのidに該当するレコードを所得して
$request->textで送られてきたデーターに更新しています
Laravel側の実装はこれで終了です

#Vue側の実装
Todo.vueを開き下記のように変更と追加をしてください

Todo.vue
<template>
    <div>
        <Header />
        <div class="main-container">
            {{ user.name }}のTodoリスト

            <v-text-field v-model="text" label="todo" required></v-text-field>
            <v-btn class="btn" @click="create">登録</v-btn>

            <template v-for="(item, index) in items">
                <v-card max-width="450" class="mx-auto" style="marign-top: 10px" :key="item.id">
                    <v-list three-line>
                        <v-list-item :key="item.id">
                            <v-list-item-content>
                                <input type="text" v-model="item.text" @keydown.enter="unforcus" @blur="update(item.id, item.text)">    //追加
                                <v-btn small @click="del(item.id, index)">完了</v-btn>
                            </v-list-item-content>
                        </v-list-item>
                    </v-list>
                </v-card>
            </template>
        </div>

    </div>
</template>

<script>
    import Header from './Header';
    import axios from 'axios';

    export default {
        components: {
            Header
        },
        metaInfo: {
            title: 'Todo',
            htmlAttrs: {
                lang: 'ja'
            }
        },
        created () {
            const user = this.$store.getters['auth/user'];
            if (user === null) {
                this.$router.push('/login');
            }

            axios.get('/api/todo')
            .then((res) => {
                this.items = res.data;
            });
        },
        computed: {
            user() {
                return this.$store.getters['auth/user'];
            }
        },
        data () {
            return {
                items: null,
                text: ''
            }
        },
        methods: {
            async create() {
                await axios.post('/api/todo', { text: this.text });

                axios.get('/api/todo')
                .then((res) => {
                    const newItem = res.data.slice(-1)[0];
                    this.items.push(newItem);
                })

                this.text = '';
            },
            async del(id, index) {
                await axios.delete('/api/todo/' + id);
                this.items.splice(index,1);
            },
            async update(id, text) {    //追加
                await axios.put('/api/todo/' + id, { text: text });

                let itemsIndex = '';
                this.items.map((value,index) => {
                    if (value.id === id) {
                        itemsIndex = index;
                    }
                });

                this.items[itemsIndex].text = text;
            },
            unforcus() {    //追加
                if (event.keyCode !== 13) {
                    return
                }

                document.activeElement.blur();
            }
        }
    }
</script>

<style>
    .main-container {
        width: 500px;
        margin: auto;
    }
    .btn {
        margin-bottom: 20px;
    }
</style>

3箇所の追加を行いました
まずこの部分ですが
<input type="text" v-model="item.text" @keydown.enter="unforcus" @blur="update(item.id, itme.text)">
input要素に内容が書き込まれEnterキーを押すことでunforcusメソッドが発火するようにしました
それによりフォームに当たっているフォーカスEnterを押すことではすずれるようになっています

Todo.vue
            unforcus(id, text) {   
                if (event.keyCode !== 13) {
                    return
                }
                document.activeElement.blur();
            }

if文の箇所ですが、この部分がなければtodoの変更でinputに日本語の入力をした際に
変換などでEnterキーを押すとそれで発火してしまいます
そのためif文での処理を追加しています
日本語入力の際の変換でのEnterをKeyCodewを299を返します
日本語入力の変換でのEnterではない(今回の場合はtodoの変更のEnter)の場合はKeyCodeを13を返します
本来発火させたいのは、後者のKeyCode13の場合です
なのでunforcusメソッドの最初でこのEnterキーは13なのかどうかをチェックしています
この処理がなければ、Enterを押すたびに処理が走ってしまうため入力途中のものなどが登録されることになりますので注意してください

また、最後の1行document.activeElement.blur()こちらでフォームのフォーカスを外しています

次にこちらのメソッドです

Todo.vue
            async update(id, text) {

                await axios.put('/api/todo/' + id, { text: text });

                let itemsIndex = '';
                this.items.map((value,index) => {
                    if (value.id === id) {
                        itemsIndex = index;
                    }
                });

                this.items[itemsIndex].text = text;
            },

こちらはフォーカスが外れることで発火するよになっています
Enterキーを押すことで、フォーカスが外れその後update()メソッドが発火し登録処理を行うと言う形です
また入力中にEnterを押されなく、クリックなどでフォーカスが外れた際にも登録処理が走るようになっています

まずLaravel側の/todoに対してtodoのidと変更内容をPUTでリクエストしています
これで、先ほど実装したLaravel側でのTodoController.phpupdate()アクションを呼び出すことができます

中の処理ですが、this.items.map()を利用し
itemsの中身のidと変更のあったidが一致するものを調べ、一致したもののindex番号を変数で保持しています
その後、this.items[itemsIndex].text - textでitemsの該当するオブジェクトに
変更内容に書き換えVueに反映するようにしています

ここまでの実装で、todoの更新ができるようになっています
表示されているtodoをクリックし、違うものに書き換えてEnterキーを入力してみてください
正常に実装できていれば、todoが編集され画面に出力されているかと思います

以上で本記事での全ての機能の実装が終わりました
会員登録、ログイン、ログアウト、todoの一覧表示、todoの新規作成、todoの削除、todoの更新
この機能を組み合わせればTodoリスト意外の開発でも同じ要領で色々な物が作れるかと思います

#最後に
今回は最後のパートとしてtodoの更新機能の実装を行いました
ここまでの9パート最後まで読んでいただきありがとうございました
少しでも、学習者の役に立てればと思いこの記事を作成しました
また、本記事では未熟である私自身が書いた記事のため
まだまだ、改善点やリファクタリング等もできるかと思いますので
このチュートリアルを進めて頂いた方々個人で取り組んで頂ければと思います。
また、間違った点や気になった点アドバイスなど御座いましたら
是非コメント頂ければと思っておりま
ありがとうございました。

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