1

So i am creating a base "TableComponent", with selectable rows etc. This TableComponent takes a prop called "buttons".
The TableComponent expects the buttons to be an array of objects like this:

buttons: [{
    label: 'Manage Themes',
    click: () => {
        if(this.selectedRows.length) {
            this.$router.push({ name: 'ManagePageOptions', query: { concernable_type: this.type, concernable_ids: this.selectedRows.map(row => row.id).join(',') }});
        } else {
            alert('Please select 1 or more company or user');
        }
    }
}]

And so in the table component, a row of buttons is created based on what is passed like so:

<b-button v-for="button in this.buttons" @click="button.click" :key="button.label"> {{ button.label }} </b-button>

Problem is that in the buttons click function, "this" refers to the parent component, and so i don't have access to the selected rows etc.

EDIT: I have found that just passing "this" to the click function solves it. Not sure if it is wise though.

buttons = [{
    label: 'Manage Pages',
    click: (vm) => {
        if(vm.selectedRows.length) {
            vm.$router.push({ name: 'ManagePageOptions', query: { concernable_type: vm.type, concernable_ids: vm.selectedRows.map(row => row.id).join(',') }});
        } else {
          alert(Lang('Please select 1 or more company or user'))
        }
    }
}];

TableComponent data:

data() {
    return {
      selectedRows: [],
      m_this: this,
    };
  },

_

<b-button v-for="button in this.buttons" @click="button.click(m_this)" :key="button.label"> {{ button.label }} </b-button>
4
  • 1
    Try adding using @click=button.click($event), and make use of a variable in the click: (obj) => {} and then check what this gives you Commented Dec 19, 2019 at 12:51
  • 2
    Sounds like an XY problem to me. In that case, the button should be emitting a click event (or any name of your choice). The consuming parent, TableComponent, will then listen to this VueJS event using the v-on or @ shorthand, and decide how to handle it thereafter. Commented Dec 19, 2019 at 12:51
  • Agree with @Terry, it's generally not advised to pass methods as props, having the child emit an event is the prescribed way Commented Dec 19, 2019 at 12:53
  • 1
    Defining the buttons using a scoped slot may also be an option that avoids this problem altogether. If you really want to stick with your current approach then I suggest passing suitable arguments to click rather than trying to grab them via this. Commented Dec 19, 2019 at 13:22

1 Answer 1

1

I agree with comments that there are better ways to do this, scoped slots is probably the best....

But, if you really want to pass functions like that you need:

  1. Change handler definition from click: () => {} to click: function() {} - reason is that this works completely different in arrow functions and as a result this is bound to the parent Vue component

  2. When passing handler into button component (inside TableComponent template), bind the handler to this of your TableComponent as described here

Sign up to request clarification or add additional context in comments.

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.