Home > database >  How to change dynamically the @click method in vue
How to change dynamically the @click method in vue

Time:10-07

I have the need of changing the method that a button executed dynamically. In Javascript, it will be as easy as giving the button and id, for example id="my-button", and then do

document.getElementById("my-button").setAttribute("onclick", "theNewMethodToExecute()")

And just like that, the button will execute the new method. How can I do that in Vue.js?

I have a simple mini-project to show my problem:

HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="./ts/generated/logic.js" defer></script>
  </head>
  <body>
    <div class="" id="app">
      <p class="">My number is:</p>
      <button @click="methodToExecute"></button>
    </div>
  </body>
</html>

index.ts (I write my Vue app in TypeScript instead of JavaScript, and I use Webpack and npm to compile my result, which compiles to a file called logic.js)

import Vue from 'vue'

const myApp = new Vue({
    data() {
        return {
            methodToExecute: "doNothing",
        };
    },
    methods: {
        doNothing() {
            console.log("Dong nothing...")
            this.methodToExecute = "doSomethingElse"
        },
        doSomethingElse() {
            console.log("Doing something else...")
        },

    },
});

myApp.$mount("#app");

In this case I tried with a property but that not work.

Note: I am aware that I can conditionally change the method like this:

v-on="{click: condition ? doWhenTrue : doWhenFalse}"

But the logic I have is much more complex, and I need to change the method programatically, the way I can do in JavaScript, How is that possible with Vue?

CodePudding user response:

Why don't you put the condition inside the method and pass an argument to it? I'm not sure on what you're trying to achieve but something like this would work for your use case.

<a @click="doNothingOrSomething(condition)"></a>

methods: {
    doNothingOrSomething(arg) {
        if (arg === 'something') {
            console.log("Doing nothing...")
        } else console.log("Doing something else...")
    }
}

Using that reasoning, the result will be:

import Vue from 'vue'

const myApp = new Vue({
    data() {
        return {
            argument: "",
        };
    },
    methods: {
        doNothingOrSomething() {
            switch (this.argument) {
                case "method1": {
                    console.log("Is method 1")
                    this.argument = "method2"
                    break;
                }
                case "method2": {
                    console.log("Is method 2")
                    this.argument = "method3"
                    break;
                }
                case "method3": {
                    console.log("Is method 3")
                    this.argument = "method1"
                    break;
                }
                default: {
                    console.log("default")
                    this.argument = "method1"
                    break;
                }
            }
        }
    },
});

myApp.$mount("#app");

and the HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="./ts/generated/logic.js" defer></script>
  </head>
  <body>
    <div class="" id="app">
      <p class="">My number is:</p>
      <button @click="doNothingOrSomething"></button>
    </div>
    <script></script>
  </body>
</html>

And that makes it work dynamically!

CodePudding user response:

you can write your condition on the click-element itself:

<button @click="methodToExecute ? doNothing() : doSomethingElse()"></button>

the first method doNothing() will be triggered if methodToExecute is true

  • Related