【Vue.js】タスク追加ページのモーダルをつくる
はじめに
タスクを追加するページのモーダルをコンポーネントとして作成します。
タスク追加ページを作成
$ touch app/javascript/pages/task/components/TaskCreateModal.vue
<template> <transition name="fade"> <div id="task-create-modal"> <div class="modal" @click.self="handleCloseModal"> // モーダル以外の部分をクリックした時にモーダルを閉じる <div class="modal-dialog"> <div class="modal-content"> <div class="modal-body"> <div class="from-group mb-3"> <label for="title">タイトル</label> <input type="text" class="form-control" id="title" v-model="task.title"> // v-modelを使って入力された内容をそのままtitleに代入 </div> <div class="from-group mb-3"> <label for="description">説明文</label> <textarea class="form-control" id="description" rows="5" v-model="task.description"></textarea> // v-modelを使って入力された内容をそのままdescriptionに代入 </div> <div class="d-flex justify-content-between"> <button type="button" class="btn btn-success" @click="handleCreateTask">追加</button> <button type="button" class="btn btn-secondary" @click="handleCloseModal">閉じる</button> </div> </div> </div> </div> </div> <div class="modal-backdrop show"></div> </div> </transition> </template> <script> export default { name: 'TaskCreateModal', data() { return { task: { title: '', description: '' } } }, methods :{ handleCloseModal() { // 閉じるボタンを押した時に親コンポーネントの'close-modal'イベントを発火 this.$emit('close-modal') }, // 第二引数で入力されたデータを渡す。 handleCreateTask() { // 追加ボタンを押したときに親コンポーネントの'create-task'イベントを発火 this.$emit('create-task', this.task) } } } </script>
<template> <div> <div class="d-flex"> <div class="col-4 bg-light rounded shadow m-3 p-3"> <div class="h4">TODO</div> <div v-for="task in tasks" :key="task.id" :id="'task-' + task.id" @click="handleShowTaskDetailModal(task)" class="bg-white border shadow-sm rounded my-2 p-4"> <span>{{ task.title }}</span> </div> <button @click="handleShowTaskCreateModal" type="button" class="btn btn-secondary"> タスクを追加 </button> </div> </div> <div class="text-center"> <router-link to="/" class="btn btn-dark mt-5">戻る</router-link> </div> <TaskDetailModal v-if="isVisibleTaskDetailModal" :task="taskDetail" @close-modal="handleCloseTaskDetailModal" /> <TaskCreateModal v-if="isVisibleTaskCreateModal" @close-modal="handleCloseTaskCreateModal" // 子コンポーネントで閉じるボタンを押した時のイベント @create-task="handleCreateTask"/> // 子コンポーネントで追加ボタンを押した時のイベント </div> </template><script> import TaskDetailModal from './components/TaskDetailModal' import TaskCreateModal from './components/TaskCreateModal' // 追加ページのコンポーネントをインポート
export default { components: { TaskDetailModal TaskCreateModal }, name: 'TaskIndex', data() { return { tasks: [], taskDetail: {}, isVisibleTaskDetailModal: false, isVisibleTaskCreateModal: false, // デフォルトでは非表示 } }, created() { this.fetchTasks(); }, methods: { fetchTasks() { this.$axios.get('tasks') .then(res => this.tasks = res.data) .catch(err => console.log(err.status)); }, handleCreateTask(task) {
try { this.$axios.post('tasks', task) // axiosを使って/tasksにpostリクエストを送る .then(res => { // ↓ postリクエストが成功した場合に擬似リロード処理を実行 this.$router.go({path: this.$router.currentRoute.path, force: true}) }); this.handleCloseTaskCreateModal(); } catch(error) { // postリクエストが失敗した場合のエラーをコンソールに表示 console.log(error) } }, handleShowTaskDetailModal { this.isVisibleTaskDetailModal = true; this.taskDetail = task; }, handleCloseTaskDetailModal() { this.isVisibleTaskDetailModal = false; this.taskDetail = {}; }, // ↓ 追加ページのモーダルの表示非表示の処理 handleShowTaskCreateModal() { this.isVisibleTaskCreateModal = true; }, handleCloseTaskCreateModal() { this.isVisibleTaskCreateModal = false; } } } </script><style scoped> </style>
完成画面