第一章11『子コンポーネントにプロパティを渡してグループ分けしたtodoを表示する』
2022/04/22 Vue.js
前回、todoを期限でグループ分けしたのでtodoGroupsの中のtodoにアクセスするためにはtodoGroups.within.today.todos[0]
というようにする必要がある。また、todoGroups.within.today
まで到達したあとの処理は期限切れ、今日のもの、明日のもの、それ以降のものに限らず同じにしたいのでtodosの中身を表示するためのコンポーネントを作成する。resources/js/components/TodoGroup.vueを作成し、以下のように編集する。
このコンポーネントではtodoの編集と削除を行うのでeditTodoという関数とdeleteTodoという関数をプロパティとして受け取る。また、期限はyyyy-mm-ddの形式で持っているが、表示する時には○月○日というように表示させたいのでそのためのformatDeadlineという関数も受け取る。calenderColorというのは期限切れのtodoに限り、カレンダーのアイコンと文字を赤くしたいのでクラスをプロパティとして渡せるようにした。todoGroupというプロパティにはtodoGroups.behind
, todoGroups.within.today
, todoGroups.within.tomorrow
, todoGroups.within.others
が入る。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<template> <div> <div v-for="todo in todoGroup.todos" :key="todo.id" class="h-16 mb-4"> <div v-on:click="editTodo(todo)"> <div class="h-7 leading-7 mb-2"> <span v-on:click.stop="deleteTodo(todo.id)" class="material-icons-outlined h-7 leading-7 align-top circle gray mr-2 cursor-pointer"> circle </span> <span class="h-7 inline-block align-top text black cursor-pointer">{{ todo.task }}</span> </div> <div class="h-7 leading-7"> <div class="h-7 leading-7 inline-block mr-4 cursor-pointer"> <span class="material-icons-outlined h-7 leading-7 align-top calender" :class="calenderColor"> calendar_today </span> <span class="h-7 inline-block align-top text w-20" :class="calenderColor">{{ formatDeadline(todo.deadline) }}</span> </div> <div v-for="label in todo.labels" class="h-7 leading-7 inline-block mr-2 cursor-pointer"> <span class="material-icons-outlined h-7 leading-7 align-top label black"> label </span> <span class="h-7 inline-block align-top text black">{{ label.title }}</span> </div> </div> </div> </div> </div> </template> <script> export default { name: "TodoGroup", props: { calenderColor: String, todoGroup: Object, editTodo: Function, deleteTodo: Function, formatDeadline: Function, }, }; </script> |
このコンポーネントをresources/js/components/TodoList.vueで使えるようにインポートする。
1 2 3 4 5 |
<script> + import TodoGroup from "./TodoGroup"; export default { + components: { TodoGroup }, data() { |
子コンポーネントに渡すための関数を作る。getTodosの下にeditTodoとdeleteTodoを追加する。
1 2 3 4 5 6 |
editTodo() { console.log("edit"); }, deleteTodo() { console.log("delete"); }, |
methodsの一番下にformatDeadline関数を追加した。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
formatDeadline(deadline) { const ymd = deadline.split("-"); let formattedDeadline = ""; if (ymd[1][0] === "0") { formattedDeadline += `${ymd[1][1]}月`; } else { formattedDeadline += `${ymd[1]}月`; } if (ymd[2][0] === "0") { formattedDeadline += `${ymd[2][1]}日`; } else { formattedDeadline += `${ymd[2]}日`; } return formattedDeadline; }, |
resources/js/components/TodoList.vueのヘッダーの下にtodoを表示するためのhtmlを書いていく。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<header class="h-28 shadow-md"> <div class="container"> <span class="logo">TODOLIST</span> </div> </header> + <div class="container bg-white my-16 p-16 shadow-md rounded-lg"> + <!--期限切れのTodo--> + <div v-if="!behindIsNull"> + <p class="text black mb-5">期限切れ</p> + <div v-for="behindTodoGroup in todoGroups.behind" :key="behindTodoGroup.deadline"> + <TodoGroup :todo-group="behindTodoGroup" :delete-todo="deleteTodo" :edit-todo="editTodo" :format-deadline="formatDeadline" calender-color="red"></TodoGroup> + </div> + <div class="border mb-12 line"></div> + </div> + + <!--Todo追加ボタン--> + <div class="mb-5 cursor-pointer" v-on:click="showAddTodoModal = true"> + <span class="material-icons-round h-7 leading-7 align-top plus purple">add</span> + <span class="h-7 inline-block align-top text purple">TODOを追加</span> + </div> + + <!--今日のTodo--> + <div v-if="!todayIsNull"> + <p class="text black mb-5">今日</p> + <TodoGroup :todo-group="todoGroups.within.today" :delete-todo="deleteTodo" :edit-todo="editTodo" :format-deadline="formatDeadline" calender-color="black"></TodoGroup> + <div v-if="!tomorrowIsNull || !othersIsNull" class="border mb-12 line"></div> + </div> + + <!--明日のTodo--> + <div v-if="!tomorrowIsNull"> + <p class="text black mb-5">明日</p> + <TodoGroup :todo-group="todoGroups.within.tomorrow" :delete-todo="deleteTodo" :edit-todo="editTodo" :format-deadline="formatDeadline" calender-color="black"></TodoGroup> + <div v-if="!othersIsNull" class="border mb-12 line"></div> + </div> + + <!--それ以降のTodo--> + <div v-if="!othersIsNull"> + <div v-for="othersTodoGroup in todoGroups.within.others" :key="othersTodoGroup.deadline"> + <p class="text black mb-5">{{ formatDeadline(othersTodoGroup.deadline) }}</p> + <TodoGroup :todo-group="othersTodoGroup" :delete-todo="deleteTodo" :edit-todo="editTodo" :format-deadline="formatDeadline" calender-color="black"></TodoGroup> + </div> + </div> + </div> |
todoの追加ボタンをクリックしたときにtodoを追加するためのモーダルを表示したいのでdataにshowAddTodoModalという変数を追加する。
1 2 3 4 5 6 7 8 9 10 11 12 |
data() { return { error: {}, todos: [], todoGroups: [], behindIsNull: true, todayIsNull: true, tomorrowIsNull: true, othersIsNull: true, + showAddTodoModal: false, }; }, |