Reputation: 29993
I am building a component which is supposed to get an Array of Objects from the parent, display them and allow for some of the Objects to be deleted (= the child sends to the parent a new Array).
A previous answer was very useful to understand the child -> parent communication but I am now stuck on an error I do no understand:
Vue.component('search-box', {
template: '#search-box-template',
props: ['who'],
methods: {
deleteID: function(p) {
var user = _.filter(this.who, function(w) {
return w.id === p.id
})
this.$emit('delete-id', user)
}
}
})
var vm = new Vue({
el: '#root',
data: {
who: [{
"name": "john",
"id": 1
}, {
"name": "mary",
"id": 2
}]
}
})
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<div id="root">
Hello in parent
<search-box v-bind:who="who" v-on:delete-id="who"></search-box>
who is: {{who}}
</div>
<template id="search-box-template">
<div>
<ul>
<li v-for="p in who">person: {{p.name}}, id: {{p.id}} <button v-on:click="deleteID(p)">delete</button></li>
</ul>
</div>
</template>
Running this code correcly lists the users, but when trying to delete one I get in the console
vue.js:1739 Uncaught TypeError: fns[i].apply is not a function
at VueComponent.invoker (vue.js:1739)
at VueComponent.Vue.$emit (vue.js:2210)
at VueComponent.deleteID (search.html:31)
at Proxy.boundFn (vue.js:170)
at click (eval at makeFunction (vue.js:9323), <anonymous>:2:164)
at HTMLButtonElement.invoker (vue.js:1743)
invoker @ vue.js:1739
Vue.$emit @ vue.js:2210
deleteID @ search.html:31
boundFn @ vue.js:170
click @ VM9358:2
invoker @ vue.js:1743
What does this error mean? Is the $emit
correct?
Upvotes: 0
Views: 246
Reputation: 29993
Following up on Linus' excellent answer, for the record below is my corrected code which emits and Array as when a user is deleted.
Vue.component('search-box', {
template: '#search-box-template',
props: ['who'],
methods: {
deleteID: function(p) {
var user = _.filter(this.who, function (w) {
return w.id != p.id
})
this.$emit('delete-id', user)
}
}
})
var vm = new Vue({
el: '#root',
data: {
who: [{
"name": "john",
"id": 1
}, {
"name": "mary",
"id": 2
}]
},
methods: {
handleDelete(users) {
this.who = users
}
}
})
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<div id="root">
Hello in parent
<search-box v-bind:who="who" v-on:delete-id="handleDelete"></search-box>
who is: {{who}}
</div>
<template id="search-box-template">
<div>
<ul>
<li v-for="p in who">person: {{p.name}}, id: {{p.id}} <button v-on:click="deleteID(p)">delete</button></li>
</ul>
</div>
</template>
Upvotes: 0
Reputation: 23978
There's two problems:
_.filter
returns an arry, so you don't emit the user, but an array containing the user. That filter is also completely unnecessary, because p
already is the user object that you intend to filter for. But that code is not the cause of the error.v-on:delete-id="who"
ere you pass an object (who
) to the event listener, but it expects a function. That's what's raising the error.A working version of your code would look like this:
Vue.component('search-box', {
template: '#search-box-template',
props: ['who'],
methods: {
deleteID: function(p) {
this.$emit('delete-id', p)
}
}
})
var vm = new Vue({
el: '#root',
data: {
who: [{
"name": "john",
"id": 1
}, {
"name": "mary",
"id": 2
}]
},
methods: {
handleDelete(person) {
const index = this.who.indexOf(person)
this.who.splice(index, 1)
}
}
})
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<div id="root">
Hello in parent
<search-box v-bind:who="who" v-on:delete-id="handleDelete"></search-box>
who is: {{who}}
</div>
<template id="search-box-template">
<div>
<ul>
<li v-for="p in who">person: {{p.name}}, id: {{p.id}} <button v-on:click="deleteID(p)">delete</button></li>
</ul>
</div>
</template>
Upvotes: 2