user2168735
user2168735

Reputation: 489

How to set @click dynamically in vue.js?

I have array of objects, where action is method from vue object.

How to set @click dynamically in v-for cycle?

I tried to use this.m1, "this.m1", "m1", but i'm getting an error:

fns.apply is not a function.

Javascript:

new Vue({
  el: "#app",
  data: {
    items: [
      { title: "Learn JavaScript", action: this.m1 },
      { title: "Learn Vue", action: "m2" },
      { title: "Play around in JSFiddle", action: "this.m3"},
      { title: "Build something awesome", action: "m4"}
    ]
  },
  methods: {
    m1() {
        console.log('1');
    },
    m2() {
        console.log('2');
    },
    m3() {
        console.log('3');
    },
    m4() {
        console.log('4');
    },
  }
})

Html:

<div id="app">
   <div v-for="item in items">
       <a @click="item.action" href="#">
         {{ item.title }}
       </a>
   </div>
</div>

Demo - https://jsfiddle.net/mezhevikin/eywraw8t/338303/

Upvotes: 1

Views: 1239

Answers (3)

Nisarg Shah
Nisarg Shah

Reputation: 14541

If you store the method names in the action property, like action: "m1", you can pass those names to a method (let's say invokeMethod) via "invokeMethod(item.action)". Now, within this invokeMethod, you can invoke the relevant functions by invoking this[methodName]() - where this[methodName] is equivalent to saying this["m1"].

var app=new Vue({
  el: "#app",
  data: {
    items: [
      { title: "Learn JavaScript", action: "m1" },
      { title: "Learn Vue", action: "m2" },
      { title: "Play around in JSFiddle", action: "m3"},
      { title: "Build something awesome", action: "m4"}
    ]
  },
  methods: {
    invokeMethod(methodName) {
        this[methodName]();
    },
    m1() {
        console.log('1');
    },
    m2() {
        console.log('2');
    },
    m3() {
        console.log('3');
    },
    m4() {
        console.log('4');
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<div id="app">
   <div v-for="item in items">
       <a @click="invokeMethod(item.action)" href="#">
         {{ item.title }}
       </a>
   </div>
</div>

Upvotes: 4

Saurabh Mistry
Saurabh Mistry

Reputation: 13669

You need to pass item object in a single method , then you do operation as per your requirement.

var app=new Vue({
  el: "#app",
  data: {
    items: [
      { title: "Learn JavaScript", action: "m1" },
      { title: "Learn Vue", action: "m2" },
      { title: "Play around in JSFiddle", action: "m3"},
      { title: "Build something awesome", action: "m4"}
    ]
  },
  methods: {
    callmethod(item) {
        console.log(item.action);
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<div id="app">
   <div v-for="item in items">
       <a @click="callmethod(item)" href="#">
         {{ item.title }}
       </a>
   </div>
</div>

Upvotes: 0

ittus
ittus

Reputation: 22393

data should be a function

new Vue({
  el: "#app",
  data () {
    return {
      items: [
        { title: "Learn JavaScript", action: this.m1 },
        { title: "Learn Vue", action: this.m2 },
        { title: "Play around in JSFiddle", action: this.m3},
        { title: "Build something awesome", action: this.m4}
     ]
    }
  },
  methods: {
    m1() {
        console.log('1');
    },
    m2() {
        console.log('2');
    },
    m3() {
        console.log('3');
    },
    m4() {
        console.log('4');
    }
  }
})

Demo https://jsfiddle.net/ojdz0r41/

Upvotes: 1

Related Questions