Sankalp Singha
Sankalp Singha

Reputation: 4546

Sending data to a non parent component in VueJs

I am trying to replicate the TODO MVC in VueJs. (Please checkout this codepen : http://codepen.io/sankalpsingha/pen/gwymJg ) I have created a component called 'todo-list' with the following code :

Vue.component('todo-list',{
  template: '#todo-list',
  props: ['todo'],
  data: function() {
    return {
    // Let us set up a isEditing Boolean so that we can know if the user
    // will edit something and we need to change the state to reflect it.
      isEditing: false,
    }
  },
  methods: {
    enableEditing: function() {
      this.isEditing = true;
    },
    editTodo: function(todo) {
      // todo.todo = todo.todo.trim();
      this.isEditing = false;
    },
    removeTodo: function(todo) {
      //this.todos.$remove(todo); // --> This part is not working?
    }
  }
});

However, I have the data defined in the app instance :

var app = new Vue({
  el: '#todo-section',
  data: {
    newTodo: '',
    todos: [
      {
        id: 1,
        todo: 'Go to the grocery',
        completed: false,
      },
      {
        id: 2,
        todo: 'See the movie',
        completed: true,
      },
      {
        id: 3,
        todo: 'Jack Reacher : Tom Cruise',
        completed: false,
      }
    ]
  },
  methods: {
    addTodo: function() {
      // This will not allow any empty items to be added.
      if(this.newTodo.trim() == '') {
        return;
      }
      this.todos.push({
        todo: this.newTodo.trim(),
        completed: false,
      });
      this.newTodo = '';
    }
  }
});

I am not able to delete a single Todo from the list. My guess is that I have to send a emit message to the app instance and put up a listener there to delete the data from it? How do I delete the data?

Upvotes: 0

Views: 429

Answers (2)

Med
Med

Reputation: 2802

It's preferable to use your methods (DeleteTodo, EditTodo...) in your parent.

var app = new Vue({
  el: '#app',
  data: {
    newTodo: '',
    todos: [{
      id: 1,
      title: 'Go to the grocery',
      completed: false
    }, {
      id: 2,
      title: 'See the movie',
      completed: true
    }, {
      id: 3,
      title: 'Jack Reacher : Tom Cruise',
      completed: false
    }]
  },

  methods: {
    addTodo: function() {
      this.todos.push({
        todo: this.newTodo.trim(),
        completed: false
      });
      this.newTodo = ''
    },

    deleteTodo: function(todo) {
      this.todos = this.todos.filter(function(i) {
        return i !== todo
      })
    }
  }
});
<div id="app">
  <ul>
    <li v-for="todo in todos">{{ todo.title }}
      <button @click.prevent="deleteTodo(todo)">
        Delete
      </button>
    </li>
  </ul>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>

Upvotes: 0

Mani Jagadeesan
Mani Jagadeesan

Reputation: 24265

When I tried to delete by clicking the x button in your codePen example, I see the error: this.$parent.todos.$remove is not a function.

I have not looked deeply into your code. But attempting to access parent component methods using this.$parent is not a good idea. Reason: a component can be used anywhere, and assuming that it will have a $parent with a particular property or method is risky.

As you suggested in your question, you need to use $emit from the child component to delete the data.

There was another similar question here few days ago, for which I created a jsFiddle: https://jsfiddle.net/mani04/4kyzkgLu/

The child component has some code like:

<button @click="$emit('delete-row')">Delete</button>

This sends out an event to parent component. Parent component can subscribe to that event using v-on as seen in that jsFiddle example.

Here is that other question for reference: Delete a Vue child component

Upvotes: 2

Related Questions