前提・実現したいこと
Vue.js Vuexを使ったカレンダーにタスクを追加出来るアプリを開発しているのですが、Vuexに追加したタスクを即座にカレンダーに反映したいです
発生している問題・エラーメッセージ
日付ごとに<td></td>をリストレンダリングしてカレンダーを作成して行きつつ、methodsプロパティ内にあるgetMessageTextメソッドによって日付オブジェクトごとに与えられた年月日(例: 2020_08_22)の値と一致する日付を持つタスクがステート内に存在する場合、<td></td>内に、<span>タスク内容</span>の形で挿入して反映しています。
新たにストアのtasks配列にフォームを通じてデータをコミットした際、リストレンダリングを再描画させ、タスクをカレンダーに反映させたいのですが上手い方法が見つからず攻めあぐねています
JavaScript
1getMessageText(calendarDate) { 2 for (let i = 0; i < this.tasks.length; i++) { 3 const message = this.tasks.filter(date => date.date === calendarDate)[0] 4 return message ? message.name : '' 5 } 6}
該当のソースコード
JavaScript(Calendar.vue)
1<template> 2 <div class="calendar-wrapper example-modal-window"> 3 <table> 4 <thead> 5 <tr> 6 <th id="prev" @click="prevPage">«</th> 7 <th id="title" colspan="5">{{getTitleDate}}</th> 8 <th id="next" @click="nextPage">»</th> 9 </tr> 10 <tr> 11 <th>Sun</th> 12 <th>Mon</th> 13 <th>Tue</th> 14 <th>Wed</th> 15 <th>Thu</th> 16 <th>Fri</th> 17 <th>Sat</th> 18 </tr> 19 </thead> 20 <tbody> 21 <tr v-for="(week, index) in createCalendar" :key="index"> 22 <td 23 v-for="day in week" 24 :key="day.fullDate" 25 :class="{disabled: day.isDisabled, today: day.isToday}" 26 @click="openModal(day.fullDate)" 27 > 28 {{day.date}} 29 <br><span>{{getMessageText(day.fullDate)}}</span> 30 </td> 31 </tr> 32 </tbody> 33 </table> 34 <my-modal @close="closeModal" v-if="modal"> 35 <p>タスクを入力してください</p> 36 <div><input type="text" v-model="message"></div> 37 <template slot="footer"> 38 <button @click="doSend">送信</button> 39 </template> 40 </my-modal> 41 </div> 42</template> 43 44<script> 45import MyModal from './MyModal.vue' 46 47export default { 48 components: { 49 MyModal 50 }, 51 data() { 52 return { 53 month: "", 54 year: "", 55 today: "", 56 modal: false, 57 message: '', 58 fullDate: '' 59 }; 60 }, 61 created() { 62 this.today = new Date(); 63 64 this.year = this.today.getFullYear(); 65 // 0 ~ 11 66 this.month = this.today.getMonth(); 67 }, 68 computed: { 69 createCalendar() { 70 const dates = [ 71 ...this.getCalendarHead, 72 ...this.getCalendarBody, 73 ...this.getCalendarTail, 74 ]; 75 // 一週間ごとのオブジェクトが配列にまとめて入っている 76 const weeks = []; 77 const weeksCount = dates.length / 7; 78 79 for (let i = 0; i < weeksCount; i++) { 80 weeks.push(dates.splice(0, 7)); 81 } 82 83 return weeks; 84 }, 85 86 getTitleDate() { 87 return `${this.year}/${String(this.month + 1).padStart(2, "0")}`; 88 }, 89 90 getCalendarHead() { 91 const dates = []; 92 const d = new Date(this.year, this.month, 0).getDate(); 93 const n = new Date(this.year, this.month, 1).getDay(); 94 95 for (let i = 0; i < n; i++) { 96 dates.unshift({ 97 date: d - i, 98 isToday: false, 99 isDisabled: true, 100 fullDate: `${this.year}_${String(this.month).padStart(2, '0')}_${String(d - i).padStart(2, '0')}`, 101 }); 102 } 103 104 return dates; 105 }, 106 107 getCalendarBody() { 108 const dates = []; // date: 日付, day: 曜日 109 const lastDate = new Date(this.year, this.month + 1, 0).getDate(); 110 111 for (let i = 1; i <= lastDate; i++) { 112 dates.push({ 113 date: i, 114 isToday: false, 115 isDisabled: false, 116 fullDate: `${this.year}_${String(this.month + 1).padStart(2, '0')}_${String(i).padStart(2, '0')}`, 117 }); 118 } 119 // 年月がthis.todayと一致するとき実行 120 if ( 121 this.year === this.today.getFullYear() && 122 this.month === this.today.getMonth() 123 ) { 124 // dates配列は0から始まる 125 dates[this.today.getDate() - 1].isToday = true; 126 } 127 128 return dates; 129 }, 130 131 getCalendarTail() { 132 const dates = []; 133 const lastDay = new Date(this.year, this.month + 1, 0).getDay(); 134 135 for (let i = 1; i < 7 - lastDay; i++) { 136 dates.push({ 137 date: i, 138 isToday: false, 139 isDisabled: true, 140 fullDate: `${this.year}_${String(this.month + 2).padStart(2, '0')}_${String(i).padStart(2, '0')}`, 141 }); 142 } 143 144 return dates; 145 }, 146 147 tasks() { 148 return this.$store.state.tasks 149 }, 150 }, 151 methods: { 152 prevPage() { 153 this.month--; 154 if (this.month < 0) { 155 this.year--; 156 this.month = 11; 157 } 158 }, 159 nextPage() { 160 this.month++; 161 if (this.month > 11) { 162 this.year++; 163 this.month = 0; 164 } 165 }, 166 openModal(value) { 167 this.modal = true 168 this.fullDate = value 169 }, 170 closeModal() { 171 this.modal = false 172 }, 173 doSend() { 174 if(this.message.length > 0) { 175 this.$store.commit('addTask', {message: this.message, date: this.fullDate}) 176 this.message = '' 177 this.closeModal() 178 } else { 179 alert('タスクを入力してください') 180 } 181 }, 182 getMessageText(calendarDate) { 183 for (let i = 0; i < this.tasks.length; i++) { 184 const message = this.tasks.filter(date => date.date === calendarDate)[0] 185 return message ? message.name : '' 186 } 187 } 188 }, 189}; 190</script> 191 192<style scoped> 193.calendar-wrapper { 194 height: 100vh; 195} 196 197table { 198 border-collapse: collapse; 199 border: 2px solid #eeeeee; 200 width: 100%; 201 height: 100%; 202 table-layout: fixed; 203} 204 205thead { 206 background: #eeeeee; 207} 208 209th, 210td { 211 padding: 8px; 212 text-align: center; 213 height: 50px; 214 border: 1px solid #eeeeee; 215} 216 217td { 218 vertical-align: top; 219} 220 221tbody td:first-child { 222 color: red; 223} 224 225tbody td:last-child { 226 color: blue; 227} 228 229td.disabled { 230 opacity: 0.3; 231} 232 233td.today { 234 font-weight: bold; 235} 236 237#prev, 238#next, 239#today { 240 cursor: pointer; 241 user-select: none; 242} 243</style>
Javascript
1import Vue from 'vue' 2import Vuex from 'vuex' 3import App from './App.vue' 4 5Vue.use(Vuex) 6 7const store = new Vuex.Store({ 8 state: { 9 tasks: [ 10 { 11 id: 1, 12 name: 'Vue.jsの勉強をする', 13 date: '2020_08_22' 14 }, 15 { 16 id: 2, 17 name: 'ご飯を食べる', 18 date: '2020_09_03' 19 } 20 ], 21 22 nextTaskId: 3 23 }, 24 mutations: { 25 addTask(state, payload) { 26 state.tasks.push({ 27 id: state.nextTaskId, 28 name: payload.message, 29 fullDate: payload.date 30 }) 31 console.log(state.tasks) 32 33 state.nextTaskId++ 34 } 35 } 36}) 37 38Vue.config.productionTip = false 39 40new Vue({ 41 store, 42 render: h => h(App), 43}).$mount('#app') 44
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。