Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js pass function as prop and make child call it with data

I have a posts list component and a post component.

I pass a method to call from the posts list to the post component, so when a button is click it will be called.

But I want to pass the post id when this function is clicked

Code:

let PostsFeed = Vue.extend({      data: function () {          return {            posts: [....]          }      },      template: `        <div>          <post v-for="post in posts" :clicked="clicked" />        </div>      `,      methods: {        clicked: function(id) {          alert(id);        }      }    }                                 let Post = Vue.extend({      props: ['clicked'],      data: function () {          return {}      },      template: `        <div>          <button @click="clicked" />        </div>      `  }

as you can see in Post component you have a click that runs a method he got from a prop, I want to add a variable to that method.

How do you do that?

like image 399
Tzook Bar Noy Avatar asked Sep 13 '16 19:09

Tzook Bar Noy


People also ask

How do I use props to pass data to child components in Vue?

The way it works is that you define your data on the parent component and give it a value, then you go to the child component that needs that data and pass the value to a prop attribute so the data becomes a property in the child component. You can use the root component (App.

Can you pass a function as prop in Vue?

While you can pass a function as a prop, this is almost always a bad idea. Instead, there is probably a feature of Vue that is designed exactly to solve your problem.

How do I get data from Vue props?

To specify the type of prop you want to use in Vue, you will use an object instead of an array. You'll use the name of the property as the key of each property, and the type as the value. If the type of the data passed does not match the prop type, Vue sends an alert (in development mode) in the console with a warning.


2 Answers

Normally, the click event handler will receive the event as its first argument, but you can use bind to tell the function what to use for its this and first argument(s):

:clicked="clicked.bind(null, post) 

Updated answer: However, it might be more straightforward (and it is more Vue-standard) to have the child emit an event and have the parent handle it.

let Post = Vue.extend({    template: `        <div>          <button @click="clicked">Click me</button>        </div>      `,    methods: {      clicked() {        this.$emit('clicked');      }    }  });    let PostsFeed = Vue.extend({    data: function() {      return {        posts: [1, 2, 3]      }    },    template: `        <div>          <post v-for="post in posts" @clicked="clicked(post)" />        </div>      `,    methods: {      clicked(id) {        alert(id);      }    },    components: {      post: Post    }  });    new Vue({    el: 'body',    components: {      'post-feed': PostsFeed    }  });
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>  <post-feed></post-feed>
like image 125
Roy J Avatar answered Oct 02 '22 18:10

Roy J


Using Vue 2 and expanding on @Roy J's code above, I created a method in the child component (Post) that calls the prop function and sends back a data object as part of the callback. I also passed in the post as a prop and used its ID value in the callback.

Back in the Posts component (parent), I modified the clicked function by referencing the event and getting the ID property that way.

Check out the working Fiddle here

And this is the code:

let Post = Vue.extend({   props: {     onClicked: Function,     post: Object   },   template: `       <div>         <button @click="clicked">Click me</button>       </div>     `,   methods: {     clicked() {         this.onClicked({         id: this.post.id       });     }   } });  let PostsFeed = Vue.extend({   data: function() {     return {       posts: [         {id: 1, title: 'Roadtrip', content: 'Awesome content goes here'},         {id: 2, title: 'Cool post', content: 'Awesome content goes here'},         {id: 3, title: 'Motorcycle', content: 'Awesome content goes here'},       ]     }   },   template: `       <div>         <post v-for="post in posts" :post="post" :onClicked="clicked" />       </div>     `,   methods: {     clicked(event) {       alert(event.id);     }   },   components: {     post: Post   } });  new Vue({   el: '#app',   components: {     'post-feed': PostsFeed   } }); 

And this is the HTML

<div id="app">     <post-feed></post-feed> </div> 
like image 37
Haret Avatar answered Oct 02 '22 18:10

Haret