1

I'm having troubles triggering a separate Vue instance method by name for each element in a v-for loop on click.

Each action corresponds to a method, but it's not triggered. What am I doing wrong?

Code:

<v-btn v-for="btn in windowControlButtons" :key="btn.id"
  @click="btn.action"
>
  <v-icon size="20px">{{btn.icon}}</v-icon>
</v-btn>
...
window: remote.getCurrentWindow(),
windowControlButtons: [
  {
    icon: 'remove',
    action: minimizeWindow()
  },
  {
    icon: 'crop_square',
    action: maximizeWindow()
  },
  {
    icon: 'close',
    action: closeWindow()
  }
]

...
methods: {
  minimizeWindow() {
    this.window.minimize()
  },
  maximizeWindow() {
    this.window.maximize()
  },
  closeWindow() {
    this.window.close()
  }
}

UPDATE

I can trigger some code directly in the data(), e.g.:

...
{
  icon: 'remove',
  action:  () => {remote.getCurrentWindow().minimize()} 
},

But what if a method wasn't as short?

How do I trigger a method already specified in methods: { }?

1 Answer 1

1

btn.action is a string, thus you can't execute it.

Every Vue instance/component method is accessible as a property in the vm.$options.methods object.

I suggest creating another method, say handleClick, to simplify your method calling depending on the button, and invoke the best suitable method from this.$options.methods as shown below.

new Vue({
  el: '#app',
  data: {
    windowControlButtons: [
      {id: 1, icon: 'remove', action: 'minimizeWindow'},
      {id: 2, icon: 'crop_square', action: 'maximizeWindow'},
      {id: 3, icon: 'close', action: 'closeWindow'}
    ]
  },
  methods: {
    handleClick(button) {
      if (this.$options.methods[button.action]) { // guard to prevent runtime errors
        this.$options.methods[button.action]();
      }
    },
    minimizeWindow() {
      console.log('minimizeWindow');
    },
    maximizeWindow() {
      console.log('maximizeWindow');
    },
    closeWindow() {
      console.log('closeWindow');
    }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>

<div id="app">
  <button v-for="btn in windowControlButtons" :key="btn.id" @click="handleClick(btn)">
    <span>{{btn.icon}}</span>
  </button>
</div>

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

3 Comments

Thank you for the answer and the code. It's odd that Vue doesn't allow you to just call a specified method. Well, I suppose that's easier said than done
Yeah. The closer it gets is this.$options.methods[button.action](). I ended up thinking this is safer than this.[button.action](), so I updated the answer. I'm leaving this comment just to let you know.
Ah, I see, that's some nice clarification there, now I know how that $options works as well. Thank you so much!

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.