2

I'm creating a to-do list in vue.js and the following piece of code in the child element returns undefined

<input v-model="titleText" type='text'>
<input v-model="projectText" type='text'>
<button class='ui basic blue button' v-on:click="sendForm()">
Create
</button>
<button class='ui basic red button' v-on:click="closeForm()">
Cancel
</button>
sendForm () {
      if (this.titleText.length > 0 && this.projectText.length > 0) {
        this.$emit('create-todo', {
          title: this.titleText,
          project: this.projectText,
          done: false
        })
      }
      this.titleText = ''
      this.projectText = ''
      this.isCreating = false
    }
  }

Parent element:

<template>
  <div id="app">
    <todo-list v-bind:todos="todos"></todo-list>
    <create-todo v-on:create-todo="createTodo()"></create-todo>
  </div>
</template>
methods: {
    createTodo (newTodo) {
      console.log(newTodo)
      this.todos.push(newTodo)
    }
}
2
  • Please show us the portion of the parent component's template where you're including the child component and handling the emitted event. This could be a simple matter of you doing v-on:create-todo="createTodo()" instead of v-on:create-todo="createTodo" or v-on:create-todo="createTodo(foo, bar, ...arguments)". Commented Nov 19, 2019 at 18:22
  • In the first example above, no arguments will be passed into the createTodo() method, which could easily be causing your problem as the emitted data would simply be ignored. In the second, the arguments will be passed in as expected. In the third, we pass in foo and bar as the first and second arguments respectively, then pass in the JavaScript ...arguments object which will unpack all additional arguments emitted by the create-todo event separately--that is, in this case, your emitted data would become the third argument. Commented Nov 19, 2019 at 18:25

2 Answers 2

3

The problem is a simple one: when you handle the create-todo event, you're explicitly invoking the createTodo() method without allowing any arguments to be passed to it. You must either allow Vue to interpret which arguments to supply implicitly by omitting the parentheses, or use a combination of spread syntax and the arguments object to explicitly pass all arguments provided by the emitted event into the method call.

Using omission:

<template>
  <div id="app">
    <todo-list v-bind:todos="todos"></todo-list>
    <create-todo v-on:create-todo="createTodo"></create-todo>
  </div>
</template>

Using spread syntax + arguments object:

<template>
  <div id="app">
    <todo-list v-bind:todos="todos"></todo-list>
    <create-todo v-on:create-todo="createTodo(...arguments)"></create-todo>
  </div>
</template>

Either solution is acceptable. If, however, you need to be able to include additional arguments into your method call in the future, then using the spread syntax + arguments object would be necessary with the additional arguments supplied before the event arguments. For example, if you wanted to supply the values "foo" and "bar" to createTodo() as well, then you would do the following:

<template>
  <div id="app">
    <todo-list v-bind:todos="todos"></todo-list>
    <create-todo v-on:create-todo="createTodo('foo', 'bar', ...arguments)"></create-todo>
  </div>
</template>
Sign up to request clarification or add additional context in comments.

Comments

0

You haven't shown the v-dom of your parent component, but perhaps you didn't insert your @create-todo listener into the custom component tag.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.