안녕하세요.
저번 포스팅에서는 작성한 TodoList를 삭제할 수 있는 Delete 기능을 구현하였습니다.
https://newbiecs.tistory.com/313
Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 9 (프론트 Delete)
안녕하세요. 저번 포스팅에서는 Create 하고 리스트를 갱신해주는 것을 만들어보았습니다. 오늘은 Delete 기능과 Vuetify DatePicker 에 선택한 날짜를 텍스트로 보여주는 것을 구현해주도록 하겠습니다
newbiecs.tistory.com
오늘은 여러 TodoList 중에 원하는 TodoList 의 Update 버튼 클릭 시 수정할 수 있는 Form 이 나오고
업데이트를 할 수 있고, 다른 TodoList 의 Update 버튼을 클릭하면 처음에 눌렀던 Update Form 은 없어지는 것을 구현해보겠습니다.
그 전에 현재 vuetify 의 date picker 가 제대로 안보이는 상황이기 때문에 백그라운드 색상을 추가해주도록 하겠습니다.
<v-date-picker style="background-color: gray" v-model="data.due_date" @input="showPicker = false"></v-date-picker>
기존에 타이틀을 생성하면 테마가 동작하지 않아 빈 칸으로 보이던 부분을 gray 색으로 채워주었습니다.
동작 예시

구현
1. App.vue
동작예시와 같은 기능을 구현하기 위해서는 is_hidden 이라는 플래그가 필요합니다.
하지만 백엔드 서버에서는 is_hidden 이라는 필드를 제공해주지 않기 때문에 생성해주도록 하겠습니다.
// HTML 에 v-on:patched:getTodoList 가 추가되었음
<todo-content v-bind:propsdata="todoList" v-on:saved="getTodoList" v-on:deleted="getTodoList"></todo-content>
import axios from "axios";
import TodoHeader from "./components/TodoHeader.vue";
import TodoContent from "./components/TodoContent.vue";
import TodoFooter from "./components/TodoFooter.vue";
let url = "http://localhost:8000/api/todo/"; // drf server addr
export default {
data: () => {
return {
todoList: []
};
},
components: {
"todo-header": TodoHeader,
"todo-content": TodoContent,
"todo-footer": TodoFooter
},
mounted() {
// DOM 객체 생성 후 drf server 에서 데이터를 가져와 todoList 저장
axios({
method: "GET",
url: url
})
.then(response => {
for (var index in response.data) {
response.data[index].is_hidden = false; // 백에서 받은 데이터에 is_hidden=false 추가
}
this.todoList = response.data;
console.log("Success", response);
})
.catch(error => {
console.log("Failed to get todoList", error.response);
});
},
methods: {
getTodoList: function() {
axios({
method: "GET",
url: url
})
.then(response => {
for (var index in response.data) {
response.data[index].is_hidden = false; // 백에서 받은 데이터에 is_hidden=false 추가
}
this.todoList = response.data;
console.log("Success", response);
})
.catch(error => {
console.log("Failed to get todoList", error.response);
});
},
updateTodoList: function() {}
}
};
TodoList 를 propsdata 로 자식컴포넌트로 전달 할 때 is_hidden 이 추가되어 전달이 됩니다.
2. TodoContent
이전 포스팅의 코드와 크게 달라진 점은 === 표시 이후를 살펴보시면 되고,
업데이트 버튼을 눌렀을 때와 is_hidden 의 동작에 대한 추가만 되었습니다.
<template>
<div>
<v-container fluid>
<v-layout column>
<v-flex>
<h3 class="subject">what is your plan?</h3>
</v-flex>
<v-flex column>
<v-row>
<v-col cols="4" md="3">
<v-text-field v-model="data.title" :counter="32" label="Title" required></v-text-field>
</v-col>
<v-col cols="4" md="3">
<v-text-field v-model="data.author" :counter="64" label="Author" required></v-text-field>
</v-col>
<v-col cols="4" md="6">
<v-text-field v-model="data.description" :counter="255" label="Content" required></v-text-field>
</v-col>
</v-row>
<div data-app>
<v-menu
v-model="showPicker"
:close-on-content-click="false"
transition="scale-transition"
offset-y
max-width="500px"
min-width="500px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="data.due_date"
label="Due Date"
hint="YYYY-MM-DD"
persistent-hint
readonly
v-on="on"
></v-text-field>
<v-date-picker
style="background-color: gray"
v-model="data.due_date"
@input="showPicker = false"
></v-date-picker>
</template>
</v-menu>
</div>
<!-- <v-date-picker v-model="data.due_date" locale="ko" no-title></v-date-picker> -->
<v-btn @click="sendForm" color="#4CAF50">create</v-btn>
<v-btn @click="clearForm" color="#F44336">clear</v-btn>
</v-flex>
================================변경 된 로직
<v-flex class="todoList" column>
<v-card fluid>
<v-list-item v-for="(data, index) in propsdata" v-bind:key="index">
<v-list-item-content v-show="!data.is_hidden"> <!-- Not 연산을 수행하기 때문에 !data.is_hidden = true 로 화면에 보이게 됩니다 -->
<v-list-item-title>{{ data.title }}</v-list-item-title>
<v-list-item-title>{{ data.author }}</v-list-item-title>
<v-list-item-title>{{ data.due_date }}</v-list-item-title>
<v-list-item-subtitle>{{ data.description }}</v-list-item-subtitle>
</v-list-item-content>
<v-form v-show="data.is_hidden"> <!-- is_hidden=true 가 되면 입력할 수 있는 form 이 보여집니다. -->
<v-container>
<v-row>
<v-col cols="12" md="6">
<v-text-field v-model="data.title" :counter="64" label="Title" required></v-text-field>
</v-col>
<v-col cols="12" md="3">
<v-text-field v-model="data.author" :counter="32" label="Author" disabled></v-text-field>
</v-col>
<v-col cols="12" md="3">
<v-text-field
v-model="data.due_date"
label="Due Date"
required
></v-text-field>
</v-col>
<v-col cols="12" md="10">
<v-text-field
v-model="data.description"
:counter="500"
label="Description"
required
></v-text-field>
</v-col>
<v-col cols="12" md="2">
<v-checkbox
v-model="data.completed"
color="#2962FF"
label="Completed"
required
></v-checkbox>
</v-col>
<v-col cols="12" md="4">
<!-- Save 버튼은 Update 버튼을 클릭하면 볼 수 있고, Save 버튼 클릭 시 is_hidden=false 를 전달합니다. -->
<v-btn class="ma-2" @click="data.is_hidden = !data.is_hidden ; updateTodo(data)" v-show="data.is_hidden" color="#4CAF50">Save</v-btn>
<!-- Delete 버튼은 Update 버튼을 클릭하면 볼 수 있고, Delete 버튼 클릭 시 선택 된 객체를 삭제합니다. -->
<v-btn class="ma-2" @click="deleteTodo(data.id)" color="#F44336">Delete</v-btn>
</v-col>
</v-row>
</v-container>
</v-form>
<!-- Update 버튼 클릭 시 onlyTodoListCard 예제에 보이는 하나의 객체만 띄울 수 있는 메소드에 데이터를 전달합니다. -->
<v-btn class="ma-2" @click="data.is_hidden = !data.is_hidden ; onlyTodoListCard(data, propsdata)" v-show="!data.is_hidden" color="#F9A825">Update</v-btn>
<!-- Delete 버튼 클릭 시 선택한 객체가 삭제 됩니다. -->
<v-btn class="ma-2" @click="deleteTodo(data.id)" v-show="!data.is_hidden" color="#F44336">Delete</v-btn>
</v-list-item>
</v-card>
</v-flex>
</v-layout>
</v-container>
</div>
</template>
다음으로 Vue.js 코드를 살펴보도록 하겠습니다.
import axios from "axios";
let url = "http://localhost:8000/api/todo/";
export default {
data: () => {
return {
showPicker: false,
data: {
id: "",
title: "",
author: "",
description: "",
due_date: new Date().toISOString().substr(0, 10)
}
};
},
props: ["propsdata"],
methods: {
sendForm: function() {
axios({
method: "POST",
url: url,
data: this.data
})
.then(response => {
console.log("Success", response);
this.$emit("saved");
})
.catch(error => {
console.log("Failed to create todoList", error.response);
});
},
clearForm: function() {
(this.data.title = ""),
(this.data.description = ""),
(this.data.author = ""),
(this.data.due_date = "");
},
deleteTodo: function(id) {
axios({
method: "DELETE",
url: url + id
})
.then(response => {
this.$emit("deleted");
console.log("Success", response);
})
.catch(error => {
console.log("Failed to delete todoList", error.response);
});
},
updateTodo: function(data) { // 사용자가 입력한 데이터를 받아 PATCH 로 업데이트
axios({
method: "PATCH",
url: url + data.id + "/",
data: data
})
.then(response => {
this.$emit("patched"); // 업데이트 후에는 상위 컴포넌트에 이벤트를 보내 getTodoList 실행
console.log("Success", response);
})
.catch(error => {
console.log("Failed to patched todoList", error.response);
});
},
onlyTodoListCard: function(data, propsdata) { // 한 개의 투두리스트만 입력 form이 보이게끔
for (var index in propsdata) {
(data.id != propsdata[index].id) ? propsdata[index].is_hidden = false : ''
}
}
}
};
Update
백엔드 서버에 구현되어있는 REST API 에 PATCH 메소드로 사용자가 수정한 데이터를 넘겨줍니다.
백엔드 서버에는 사용자가 입력한 정보가 업데이트 되었지만, 페이지를 새로고침을 해야만 변경 된 데이터가 보이기 때문에
this.$emit("patched") 로 이벤트를 발생시켜 상위컴포넌트에서 새로운 TodoList 를 받아오도록 해주었습니다.
onlyTodoListCard
TodoList 목록들에 수정할 수 있게 Update 버튼들이 위치해있습니다.
Hello 와 Dude 라는 투두리스트가 있다고 가정하겠습니다.
Hello 를 클릭하여 정보를 수정하고, Dude 를 클릭하여 정보를 수정할 때 기존에 열려있던 Hello 는 닫히도록 해주는 함수입니다.

최근에 자격증 시험을 치뤄서 공부한다고 포스팅이 많이 늦어졌네요.
다음 포스팅에서는 디자인 적인 요소와 Header, Footer 의 구색을 맞춰보도록 하겠습니다.
감사합니다!
'Project > Django & Vue.js' 카테고리의 다른 글
| Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 11 (프론트 디자인) (2) | 2020.08.26 |
|---|---|
| Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 9 (프론트 Delete) (0) | 2020.08.09 |
| Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 8-1 (프론트 todoList 보충) (0) | 2020.08.06 |
| Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 8 (프론트 todoList Create) (0) | 2020.08.04 |
| Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 7 (프론트 todoList GET) (0) | 2020.07.31 |
댓글