8
votes

I am trying to make my Vue Component reusable but there is a part in it which requires to run a function on button click which I have defined in the parent component. The component's button will always run a parent function and the parameter it passes is always the same (its only other property).

Right now I am passing 2 properties to the component: 1) an object and 2) the parent function reference, which requires the object from 1) as a parameter.

The Child-Component looks like this (stripped unnecessary code):

<button v-on:click="parentMethod(placement)">Analyze</button>

Vue.component('reporting-placement', {
    props: ['placement', 'method'],
    template: '#reporting-placement',
    methods: {
        parentMethod: function(placement) {
            this.method(placement);
        }
    }
});

The parent is making use of the child like this:

<reporting-placement v-bind:placement="placement" v-bind:method="analyzePlacement"></reporting-placement>

methods: {
        analyzePlacement: function(placement) {
            this.active_placement = placement;
        },
    }

As you can see, the child has only one property, placement, and the callback reference. The placement must be put in as a parameter to the reference function from the parent.

But since the parent defines the parameters, the child shouldn't concern itself with what it needs to pass to the parent function. Instead I would prefer to already pass the parameter along in the parent.

So instead of

<reporting-placement v-bind:placement="placement" v-bind:method="analyzePlacement"></reporting-placement>

I would prefer

<reporting-placement v-bind:placement="placement" v-bind:method="analyzePlacement(placement)"></reporting-placement>

(including appropriate changes in the child). But passing the parameter along does not work that way. Is it possible (maybe in other syntax) to 'bind' the variable to the function reference so that it is automatically passed along when the callback is called?

Info: I don't get an error message if I write it down as above but the whole Vue screws up when I pass the parameter along to the component.

Hope the issue is clear :-) Thanks a lot!

1
Vue has a one way data flow, if you need to call a method in the parent $emit the data back to parent and do it there. If you need the method in the child, put it in the child, and if you need the method in multiple components use a mixin. Don't pass methods through props unless you have a specific reason to do so.craig_h
This might be helpful. But generally it does seem like all you need to do is emit an event from the component.Bert

1 Answers

5
votes

By reading your proposal I've found out that you are overusing the props passing.

Your concern that child component should not have any knowledge about the way that the parent component uses the data is completely acceptable. To achieve this you can use Vue's event broadcasting system instead of passing the method as props. So your code will become something like this:

Vue.component('reporting-placement', {
   props: ['placement', 'method'],
   template: '#reporting-placement',
   methods: {
       parentMethod: function(placement) {
           this.$emit('reporting-placement-change', placement)
       }
   }
});

And you can use it like this:

<reporting-placement v-bind:placement="placement" @reporting-placement-change="analyzePlacement($event)"></reporting-placement>

But if you need the data which is provided by the method from parent it's better to consider using a state management system (which can be a simple EventBus or event the more complex Vuex)

And finally, if you really like/have to pass the method as a prop, You can put it in an object, and pass that object as prop.