第一章10 『取得したtodoを期限でグループ分けする』
2022/04/18 Vue.js
取得した後に期限ごとにグループ分けをしたいので関数を追加する。
まず、getTodos関数によって取得したtodosはidの昇順になっているので、期限の日付で並び替えを行う。
以下の関数をmethodsに追加する。getTodos関数で取得してきたtodosをdataのtodos(以後this.todos)に入れ、this.todosの中に入っている要素数が2つより少なければ並べ替えを行う必要がないのでreturnする。要素数が2つ以上の場合は各todoのdeadline (ex. "2022-01-01") を元にDateオブジェクトを生成したものを使って比較する。この関数では期限の古いものが配列の先頭に来るように並び替えることができる。
1 2 3 4 5 6 |
sortTodoByDeadLine() { if (this.todos.length < 2) return; this.todos = this.todos.sort( (a, b) => new Date(a.deadline) - new Date(b.deadline) ); }, |
次に、todoを期限切れ、今日のもの、明日のもの、それ以降のものでグループ分けをしたいので以下のようにgroupTodoByDeadlineという関数をmethods内に作成する。
1 2 3 |
groupTodoByDeadLine() { }, |
v-ifを使って要素を表示するかを切り替えるので、todos.hogehoge.length > 0
と書いて判定するのではなく、要素の有無を表す変数を作る。
1 2 3 4 5 6 7 8 9 10 |
data() { return { error: {}, todos: [], + behindIsNull: true, + todayIsNull: true, + tomorrowIsNull: true, + othersIsNull: true, } }, |
groupTodoByDeadLine関数では期限切れ、今日、明日、それ以降のものにグループ分けを行うので、今日と明日の日付の文字列を生成するための関数をmethodsに追加する。以下の関数ではDateオブジェクトから日付の文字列を生成した時にyyyy-mm-ddの形式に統一するための処理が書いてある。今日の日付の文字列を取得するためにはaddDaysに0を入れ、明日の日付の文字列を取得する時はaddDaysに1を入れる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
getDateString(date, addDays) { let dateString = ""; dateString += `${date.getFullYear()}-`; if (`${date.getMonth() + 1}`.length === 1) { dateString += "0"; } dateString += `${date.getMonth() + 1}-`; if (date.getDate().toString().length === 1) { dateString += "0"; } dateString += `${date.getDate() + addDays}`; return dateString; }, |
groupTodoByDeadLine関数の処理を書いていく。今日と明日の日付の文字列をgetDateString関数を使って定数に入れておく。
1 2 |
const today = this.getDateString(new Date(), 0); //ex. '2022-04-18' const tomorrow = this.getDateString(new Date(), 1); //ex. '2022-04-19' |
todoを日付でグループ分けする時に同じ日付のものを入れておく変数を初期化するための関数をgroupTodoByDeadLine関数の中に作り、todoGroupという変数を作っておく。
1 2 3 4 5 6 7 |
const newTodoGroup = () => { return { deadline: "", todos: [], }; }; let todoGroup = newTodoGroup(); |
todoGroupをまとめておくtodoGroupsという変数を作る。この変数では最初から期限切れ、今日のもの、明日のもの、それ以降のものを入れておくための配列やオブジェクトを作っておく。
1 2 3 4 5 6 7 8 |
let todoGroups = { behind: [], within: { today: {}, tomorrow: {}, others: [], }, }; |
次に、todoGroupをtodoGroupsに入れるための関数をgroupTodoByDeadLine関数の中に作る。この関数ではdeadlineを元に期限切れ、今日のもの、明日のもの、それ以降のものを判定して振り分けを行う。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
const pushToTodoGroups = (todoGroup) => { if (todoGroup.deadline === "") return; if (new Date(todoGroup.deadline) < new Date(today)) { todoGroups.behind.push(todoGroup); this.behindIsNull = false; } if (todoGroup.deadline === today) { todoGroups.within.today = todoGroup; this.todayIsNull = false; } if (todoGroup.deadline === tomorrow) { todoGroups.within.tomorrow = todoGroup; this.tomorrowIsNull = false; } if (new Date(todoGroup.deadline) > new Date(tomorrow)) { todoGroups.within.others.push(todoGroup); this.othersIsNull = false; } }; |
最後に、todosをforで回して日付の変わるタイミングでpushToTodoGroups関数を呼び出したりtodoGroupのtodosにtodoを追加したりする。 behindIsNull などの要素があるかを判定するための変数も初期化する。for文が終わったらtodoGroupsをdataのtodoGroupsに代入したいのでdataにtodoGroupsを追加する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
this.behindIsNull = true; this.todayIsNull = true; this.tomorrowIsNull = true; this.othersIsNull = true; for (let i = 0; i < this.todos.length; i++) { if (this.todos[i].deadline !== todoGroup.deadline) { pushToTodoGroups(todoGroup); todoGroup = newTodoGroup(); todoGroup.deadline = this.todos[i].deadline; } todoGroup.todos.push(this.todos[i]); if (i === this.todos.length - 1) { pushToTodoGroups(todoGroup); } } this.todoGroups = todoGroups; |
1 2 3 4 5 6 7 8 9 10 11 |
data() { return { error: {}, todos: [], + todoGroups: [], behindIsNull: true, todayIsNull: true, tomorrowIsNull: true, othersIsNull: true, }; }, |
最終的にgroupTodoByDeadLine関数は以下のようになった。
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
groupTodoByDeadLine() { const today = this.getDateString(new Date(), 0); const tomorrow = this.getDateString(new Date(), 1); const newTodoGroup = () => { return { deadline: "", todos: [], }; }; let todoGroup = newTodoGroup(); let todoGroups = { behind: [], within: { today: {}, tomorrow: {}, others: [], }, }; const pushToTodoGroups = (todoGroup) => { if (todoGroup.deadline === "") return; if (new Date(todoGroup.deadline) < new Date(today)) { todoGroups.behind.push(todoGroup); this.behindIsNull = false; } if (todoGroup.deadline === today) { todoGroups.within.today = todoGroup; this.todayIsNull = false; } if (todoGroup.deadline === tomorrow) { todoGroups.within.tomorrow = todoGroup; this.tomorrowIsNull = false; } if (new Date(todoGroup.deadline) > new Date(tomorrow)) { todoGroups.within.others.push(todoGroup); this.othersIsNull = false; } }; this.behindIsNull = true; this.todayIsNull = true; this.tomorrowIsNull = true; this.othersIsNull = true; for (let i = 0; i < this.todos.length; i++) { if (this.todos[i].deadline !== todoGroup.deadline) { pushToTodoGroups(todoGroup); todoGroup = newTodoGroup(); todoGroup.deadline = this.todos[i].deadline; } todoGroup.todos.push(this.todos[i]); if (i === this.todos.length - 1) { pushToTodoGroups(todoGroup); } } this.todoGroups = todoGroups; }, |
groupTodoByDeadLine関数の処理が完了するとthis.todoGroupsにはこんな感じの構造のデータが入る。
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
let todoGroups = { behind: [ { deadline: "2022-04-16", todos: [ { id: 1, task: "test1", deadline: "2022-04-16", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", labels: [ { id: 3, title: "Blog", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", pivot: { todo_id: 1, label_id: 3 }, }, ], }, ], }, { deadline: "2022-04-17", todos: [ { id: 2, task: "test2", deadline: "2022-04-17", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", labels: [ { id: 1, title: "Work", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", pivot: { todo_id: 2, label_id: 1 }, }, ], }, ], }, ], within: { today: { deadline: "2022-04-18", todos: [ { id: 3, task: "test3", deadline: "2022-04-18", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", labels: [ { id: 1, title: "Work", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", pivot: { todo_id: 3, label_id: 1 }, }, ], }, ], }, tomorrow: { deadline: "2022-04-19", todos: [ { id: 5, task: "test4", deadline: "2022-04-19", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", labels: [ { id: 3, title: "Blog", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", pivot: { todo_id: 5, label_id: 3 }, }, ], }, ], }, others: [ { deadline: "2022-04-20", todos: [ { id: 7, task: "test5", deadline: "2022-04-20", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", labels: [ { id: 1, title: "Work", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", pivot: { todo_id: 7, label_id: 1 }, }, ], }, ], }, { deadline: "2022-04-21", todos: [ { id: 9, task: "test6", deadline: "2022-04-21", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", labels: [ { id: 1, title: "Work", created_at: "2022-04-18 03:34:15", updated_at: "2022-04-18 03:34:15", pivot: { todo_id: 9, label_id: 1 }, }, ], }, ], }, ], }, }; |
最後に、getTodosにsortTodoByDeadLine関数とgroupTodoByDeadLine関数を追加すればtodoの取得時に行う処理は終わり。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
getTodos() { axios .get("api/todos") .then((response) => { if (Object.keys(response.data).length === 0) { this.todos = []; } else { this.todos = response.data; } this.sortTodoByDeadLine(); this.groupTodoByDeadLine(); }) .catch((error) => { if (error.response) { this.error = { status: error.response.status, message: error.response.data.message, }; } }); }, |