Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 9 (프론트 Delete)
Project/Django & Vue.js

Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 9 (프론트 Delete)

뉴비뉴 2020. 8. 9.

안녕하세요.

 

저번 포스팅에서는 Create 하고 리스트를 갱신해주는 것을 만들어보았습니다.

오늘은 Delete 기능과 Vuetify DatePicker 에 선택한 날짜를 텍스트로 보여주는 것을 구현해주도록 하겠습니다.

 

https://newbiecs.tistory.com/312

 

Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 8-1 (프론트 todoList 보충)

안녕하세요. https://newbiecs.tistory.com/310 Vue 와 Django(DRF) 를 이용하여 Todo 리스트 만들기 - 8 (프론트 todoList Create) 안녕하세요. newbiecs.tistory.com/309 Vue 와 Django(DRF) 를 이용하여 Todo..

newbiecs.tistory.com

DatePicker 선택한 날짜를 텍스트로

전 포스팅을 보시면 아시겠지만 날짜를 클릭해도 우리가 정확히 날짜를 선택하였는지 확인하기가 어렵습니다.

원래는 color 를 지정해주면 DatePicker 에 컬러가 적용이되는데 이상하게 제 환경에서는 컬러가 표시가 되지 않네요;

컬러테마가 적용되지 않는 부분에 대해 아시는분이 계시면 댓글 달아주시면 감사하겠습니다.

문제를 해결하기 위해 검색하던 도중 스택오버플로우에서 텍스트로 출력해주는 코드를 찾았고 투두 프로젝트에 적용시켜 보겠습니다.

 

기존의 코드를 제거하고 해당 위치에 아래 코드를 붙여넣겠습니다.

<!-- TodoContent.vue -->


<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>



<!-- 추가 된 부분 -->
<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 v-model="data.due_date" no-title @input="showPicker=false"></v-date-picker>
  </template>
</v-menu>
<!-- <v-date-picker v-model="data.due_date" locale="ko" no-title></v-date-picker> -->



          <v-btn @click="sendForm" style="background: green">create</v-btn>
          <v-btn @click="clearForm" style="background: red">clear</v-btn>
        </v-flex>
        <v-flex class="todoList" column>
          <v-card max-width="600" tile>
            <v-list-item v-for="(data, index) in propsdata" v-bind:key="index">
              <v-list-item-content>
                <v-list-item-title>{{ data.title }}</v-list-item-title>
                <v-list-item-subtitle>{{ data.description }}</v-list-item-subtitle>
              </v-list-item-content>
            </v-list-item>
          </v-card>
        </v-flex>
      </v-layout>
    </v-container>
  </div>
</template>

Vue 에는 showPicker를 추가해주도록 하겠습니다.

export default {
  data: () => {
    return {
      showPicker: false,  // 추가
      data: {
        title: "",
        author: "",
        description: "",
        due_date: new Date().toISOString().substr(0, 10),
      },
    };
  },
  

// 초기화 시켜주는 부분에도 due_date 를 추가해주도록 하겠습니다.
clearForm: function() {
      (this.data.title = ""),
      (this.data.description = ""),
      (this.data.author = ""),
      (this.data.due_date = "")
    }

날짜를 클릭하면 값이 변경된다.

Delete 기능 구현하기

우리는 백엔드 서버에 삭제하는 기능을 만들어두었습니다. 그것을 이용하여 만들어봐야겠죠?

요청을 보내려고 알아보니 백엔드 프로젝트에서 몇 가지 빠진 구성이 있어 수정을 하도록 하겠습니다.

 

백엔드 프로젝트에 TodoSerializer 라는 곳을 가보면

serializers/todo.py

Todo 모델에서 가져올 필드들을 명시해 주었는데 여기에 우리는 id라는 것을 추가해야 합니다.

보통 삭제할 때 투두 객체의 id 값으로 삭제를 하기 때문입니다.

 

fields 맨 앞에 id 를 추가해주고, localhost:8000 으로 접속하여 id 가 제대로 출력되는지 확인해보겠습니다.

추가한 ID 가 잘 출력 됨

다시 프론트 프로젝트로 넘어와서 버튼을 생성해주고, 이벤트 설정, axios 요청을 구현하도록 하겠습니다.

버튼을 생성하면서 기존에 있던 버튼들의 color 도 v-btn 의 props color 를 이용하여 같이 변경해주겠습니다.

<!-- TodoContent.vue -->

<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>
            <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 v-model="data.due_date" no-title @input="showPicker = false"></v-date-picker>
              </template>
            </v-menu>
            <!-- <v-date-picker v-model="data.due_date" locale="ko" no-title></v-date-picker> -->
          <v-btn @click="sendForm" color="#4CAF50">create</v-btn> <!-- color 변경 -->
          <v-btn @click="clearForm" color="#F44336">clear</v-btn> <!-- color 변경 -->
        </v-flex>
        <v-flex class="todoList" column>
          <v-card max-width="600" tile>
            <v-list-item v-for="(data, index) in propsdata" v-bind:key="index">
              <v-list-item-content>
                <v-list-item-title>{{ data.title }}</v-list-item-title>
                <v-list-item-subtitle>{{ data.description }}</v-list-item-subtitle>
              </v-list-item-content>
              <v-btn class="ma-2" @click="deleteTodo(data.id)" color="#F44336">Delete</v-btn> <!-- color 변경 -->
            </v-list-item>
          </v-card>
        </v-flex>
      </v-layout>
    </v-container>
  </div>
</template>

기존 버튼 색상 변경과 DELETE 버튼 생성

다음으로 deleteTodo method 를 생성하겠습니다.

// TodoContent.vue


deleteTodo: function(id) {
      axios({
        method: "DELETE",
        url: url + id, // localhost:8000/api/todo/1
      })
        .then(response => {
          this.$emit("deleted"); // 상위 컴포넌트에 이벤트를 전송
          console.log("Success", response);
        })
        .catch(error => {
          console.log("Failed to get todoList", error.response);
        });
    }

deleteTodo 에서 id 를 인자로 받아 백엔드에서 넘겨준 id 를 받습니다.

method 를 DELETE 로 수정하고, url 에 id 를 포함시켜 요청을 보면 백엔드 서버에서 삭제가 이뤄집니다.

 

DELETE 버튼을 누르면 삭제는 되지만 바로 동기화가 되지 않는 것을 볼 수 있습니다.

이것은 Create 와 동일함으로 자세한 설명을 생략하겠습니다.

($emit("deleted") 로 상위컴포넌트에 이벤트를 전달합니다.

<!-- App.vue -->


<template>
  <div>
    <todo-header></todo-header>
    <todo-content 
    v-bind:propsdata="todoList" 
    v-on:saved="getTodoList" 
    v-on:deleted="getTodoList"></todo-content> <!-- deleted 라는 이벤트가 수신이 감지되면 getTodoList 메소드 실행 -->
    <!-- v-bind:하위컴포넌트 속성명="상위 컴포넌트 전달할 데이터명"  -->
    <!-- v-on:하위컴포넌트 이벤트 전달 속성명="상위 컴포넌트 메소드명"  -->
    <todo-footer></todo-footer>
  </div>
</template>



<script>
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 => {
        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 => {
          this.todoList = response.data;
          console.log("Success", response);
        })
        .catch(error => {
          console.log("Failed to get todoList", error.response);
        });
    },
    updateTodoList: function() {},
  }
};
</script>

methods 에 deleteTodoList 는 사용하지 않기 때문에 제거해주고, 제대로 동작하는지 확인해보겠습니다.

 

Goods

감사합니다.

 

전체적인 코드가 궁금하신분은

https://github.com/2044smile

 

2044smile - Overview

Python/Django. 2044smile has 32 repositories available. Follow their code on GitHub.

github.com

여기서 Todo-backend, Todo-frontend 를 보시면 되겠습니다.

Reference

- https://stackoverflow.com/questions/57696615/vuetify-how-to-fix-v-date-picker-not-showing-the-chosen-date-in-the-text-field

 

Vuetify: How to fix v-date-picker not showing the chosen date in the text-field

I'm creating a form with vue.js / vuetify 2, one of the field is Date Event, so I used v-date-picker for the user to choose the date. The problems are the following: Date Picker menu opens, but ca...

stackoverflow.com

- https://vuetifyjs.com/ko/styles/colors/#material-colors

 

Material color palette — Vuetify.js

Learn about the colors of Material Design. Consume the javascript color pack directly in your application.

vuetifyjs.com

댓글

💲 추천 글