티스토리 뷰

728x90

지난 글에 이어 이번에는 수정 기능을 추가했다. 😀

 

할 일 목록을 추가할 때와 수정할 때 폼이 동일해서 TodoInpuForm이라는 컴포넌트로 분리했고 추가, 수정 함수를 callback props로 받았다. 추가, 수정일 때 버튼의 문자도 다르게 노출시켰다. 수정 일 때는 입력한 텍스트를 노출해야 하기 때문에 옵션으로 기본 텍스트 값을 추가했다.

 

// TodoInputForm.vue
<template>
  <div>
    <input v-model="input" type="text" @keyup="keyupInput">
    <button type="button" @click="updateTodo">
      {{ mode === 'add' ? 'ADD' : 'EDIT' }}
    </button>
  </div>
</template>

<script>
export default {
  props: {
    callback: {
      type: Function,
      required: true
    },
    mode: {
      type: String,
      default: 'add'
    },
    defaultText: {
      type: String,
      default: '',
      required: false
    }
  },
  data () {
    return {
      input: this.defaultText
    }
  },
  methods: {
    updateTodo () {
      if (this.input.trim() === '') { return }

      this.callback(this.input)
    },
    keyupInput (event) {
      if (event.key !== 'Enter') { return }

      this.updateTodo(this.input)
    }
  }
}
</script>

 

할 일을 추가할 때는 defaultText가 필요하지 않기 때문에 props를 생략했고 수정할 때는 defaultText를 props로 전달했다.

 

// pages/create.vue
<template>
  <div>
    <h1>Create Todo</h1>
    <todo-input-form :callback="add" :mode="`add`" />
  </div>
</template>

<script>
import { mapActions } from 'vuex'
import TodoInputForm from '~/components/TodoInputForm'
export default {
  components: {
    TodoInputForm
  },
  methods: {
    add (input) {
      this.createTodo(input)

      // redirect list
      this.$router.push('/')
    },
    ...mapActions(['createTodo'])
  }
}
</script>
// pages/edit.vue
<template>
  <div>
    <h1>Edit Todo</h1>
    <todo-input-form :callback="edit" :mode="`edit`" :default-text="selectedTodo && selectedTodo.text" />
  </div>
</template>

<script>
import { mapActions, mapState } from 'vuex'
import TodoInputForm from '~/components/TodoInputForm'

export default {
  components: {
    TodoInputForm
  },
  computed: {
    ...mapState({ selectedTodo: state => state.selectedTodo })
  },
  methods: {
    edit (input) {
      this.editTodo(input)

      // redirect list
      this.$router.push('/')
    },
    ...mapActions(['editTodo'])
  }
}
</script>

 

UI는 동일하고 기능만 다르기 때문에 분리한 컴포넌트를 추가하고 actions에서 구현한 기능을 가져와 그대로 사용했다.

 

// pages/index.vue
<template>
  <div id="app">
    <ul>
      <li v-for="todo in todos" :key="todo.id">
        <input :checked="todo.completed" type="checkbox" @change="toggleTodo(todo.id)">
        <nuxt-link :to="`/todo/${todo.id}`">
          <span @click="setTodo(todo)">{{ todo.text }}</span>
        </nuxt-link>
        <button type="button" @click.prevent="removeTodo(todo.id)">
          delete
        </button>
        <nuxt-link :to="`/todo/edit`">
          <button type="button" @click="setTodo(todo)">
            edit
          </button>
        </nuxt-link>
      </li>
    </ul>
  </div>
</template>

<script>
import { mapGetters, mapActions } from 'vuex'
export default {
  methods: {
    ...mapActions(['removeTodo', 'toggleTodo', 'setTodo'])
  },
  computed: {
    ...mapGetters({
      todos: 'getFilteredTodos'
    })
  }
}
</script>

<style scoped>
ul{padding:0px}
li{list-style:none}
</style>

 

edit 버튼을 추가하고 nuxt-link로 연결했다. edit 버튼을 클릭하면 선택한 할 일 목록을 vuex에 담고 가져다 쓰도록 했다. id 기반으로 동작하는 방법으로 구현도 가능하시만 쉽게 할 요령으로 간단히 구현했다.

 

아래는 최종 결과 화면이다.

 

 

다음 시간에는 axio로 데이터를 API로 가져오고, 추가하고, 수정하고 삭제하는 기능을 구현할 예정이다.

 

 

도움이 되셨다면 공감❤️ 눌러주세요.

728x90
댓글