Skip to content
Advertisement

How do you target a button, which is in another component, with a method in App.vue?

I’m making a basic To Do app, where I have an input field and upon entering a task and pressing the “Enter” key the task appears in the list. Along with the task the TodoCard.vue component also generates a button, which I would like to use to delete the task.

I’ve added a @click="removeTodo" method to the button, but don’t know where to place it, in the TodoCard component or in the App.vue file?

TodoCard component:

<template>
  <div id="todo">
    <h3>{{ todo.text }}</h3>
    <button @click="removeTodo(todo)">Delete</button>
  </div>
</template>

<script>
export default {
  props: ['todo'],
  methods: {
    removeTodo: function (todo) {
  this.todos.splice(this.todos.indexOf(todo), 1)
    }
  }
}
</script>

App.vue:

<template>
  <div id="app">
    <input class="new-todo"
    placeholder="Enter a task and press enter."
    v-model="newTodo"
    @keyup.enter="addTodo">
    <TodoCard v-for="(todo, key) in todos" :todo="todo" :key="key" />
  </div>
</template>

<script>
import TodoCard from './components/TodoCard'

export default {
  data () {
    return {
      todos: [],
      newTodo: ''
    }
  },
  components: {
    TodoCard
  },
  methods: {
    addTodo: function () {
      // Store the input value in a variable
      let inputValue = this.newTodo && this.newTodo.trim()

      // Check to see if inputed value was entered
      if (!inputValue) {
        return
      }

      // Add the new task to the todos array
      this.todos.push(
        {
          text: inputValue,
          done: false
        }
      )

      // Set input field to empty
      this.newTodo = ''
        }
      }
    }
    </script>

Also is the code for deleting a task even correct?

Advertisement

Answer

You can send an event to your parent notifying the parent that the delete button is clicked in your child component.

You can check more of this in Vue’s documentation.

And here’s how your components should look like:

TodoCard.vue:

<template>
  <div id="todo">
    <h3>{{ todo.text }}</h3>
    <button @click="removeTodo">Delete</button>
  </div>
</template>

<script>
export default {
  props: ['todo'],
  methods: {
    removeTodo: function (todo) {
       this.$emit('remove')
    }
  }
}
</script>

App.vue:

<template>
  <div id="app">
    <input class="new-todo"
    placeholder="Enter a task and press enter."
    v-model="newTodo"
    @keyup.enter="addTodo">
    <TodoCard v-for="(todo, key) in todos" :todo="todo" :key="key" @remove="removeTodo(key)" />
  </div>
</template>

<script>
import TodoCard from './components/TodoCard'

export default {
  data () {
    return {
      todos: [],
      newTodo: ''
    }
  },
  components: {
    TodoCard
  },
  methods: {
    addTodo: function () {
      // Store the input value in a variable
      let inputValue = this.newTodo && this.newTodo.trim()

      // Check to see if inputed value was entered
      if (!inputValue) {
        return
      }

      // Add the new task to the todos array
      this.todos.push(
        {
          text: inputValue,
          done: false
        }
      )

      // Set input field to empty
      this.newTodo = ''
        }
      },
     removeTodo: function(key) {

       this.todos.splice(key, 1);

     }
    }
    </script>
Advertisement