0

Ok, so, be warned that this is a very newbie question since I'm only getting started with Vue.js.

So, I have a label and a button. If the label is not visible, the button should say "Show Label" and when clicked... show the label. When the label is visible, the button should say "Hide Label" and when clicked, hide it.

This (with computed properties) shows/hides the label, but does not change the button caption:

<html>
    <head>
        <link rel="stylesheet" href="index.css">
        <script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
    </head>
    <body>

        <div id="app">
            {{ message }}
            This is another thing: <b>{{thing}}</b><br>
            <span :title="title" @click="doSomething">NO TITLE</span>
            <ul v-for="item in items">
                <li>{{item}}</li>
            </ul>
            <button @click="labelVisible=!labelVisible">{{toggleMessage}}</button>
            <label v-if="labelVisible">This is my label</label>
        </div>
    </body>
    <script>
        var app = new Vue({ 
            el: '#app',
            data: {
                message: 'Hello Vue!',
                thing: 'thing',
                title: "This is the title",
                doSomething: ()=>{
                    alert("did something")
                },
                items: ["one", "two", "three"],
                labelVisible: true
            },
            computed: {
                toggleMessage: ()=>{
                    if (this.labelVisible) {
                        return "Hide Label";
                    }
                    else {
                        return "Show Label";
                    }
                }
            }
        });
    </script>
</html>

This one (just with an on:click binding) doesn't do anything:

<html>
    <head>
        <link rel="stylesheet" href="index.css">
        <script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
    </head>
    <body>

        <div id="app">
            {{ message }}
            This is another thing: <b>{{thing}}</b><br>
            <span :title="title" @click="doSomething">NO TITLE</span>
            <ul v-for="item in items">
                <li>{{item}}</li>
            </ul>
            <button @click="buttonClicked">{{toggleMessage}}</button>
            <label v-if="labelVisible">This is my label</label>
        </div>
    </body>
    <script>
        var app = new Vue({ 
            el: '#app',
            data: {
                message: 'Hello Vue!',
                thing: 'thing',
                title: "This is the title",
                doSomething: ()=>{
                    alert("did something")
                },
                items: ["one", "two", "three"],
                labelVisible: true,
                toggleMessage: "Hide Label",
                buttonClicked: ()=> {
                    this.labelVisible = !this.labelVisible;
                    if (this.labelVisible) {
                        this.toggleMessage = "Hide Label";
                    }
                    else {
                        this.toggleMessage = "Show Label";
                    }
                }
            }
        });
    </script>
</html>

Preferably, I would like to get both of them working. But I still cannot see what I'm doing wrong. The Vue DevTools report no issue whatsoever...


UPDATE:

In the second case, when printing out the values of labelVisible and toggleMessage, they do change fine. It's just that the change is not reflected in the component.

Dr.Kameleon
  • 22,532
  • 20
  • 115
  • 223
  • 1
    It's because of an arrow functions, you can't do it because `this` there is not Vue's. More about this here: https://stackoverflow.com/a/42971173/3125477 – Alex Brohshtut Apr 02 '20 at 06:49
  • @AlexBrohshtut OK, so, I made the change in the first example (with computed properties) and it seems like what you suggest is true: eliminating the fat-arrow function declaration did work. The second example however, still doesn't work. (Perhaps, Vue doesn't know it has to re-render the component after the "manual" data change?) – Dr.Kameleon Apr 02 '20 at 06:52
  • 1
    But second example also contains arrow function: `buttonClicked: ()=>` – Alex Brohshtut Apr 02 '20 at 07:00
  • @AlexBrohshtut Yep, it does. The thing is I fixed that part, but it's still not working. – Dr.Kameleon Apr 02 '20 at 07:02
  • @AlexBrohshtut Jesus, just spotted it. Such a newbie miss... – Dr.Kameleon Apr 02 '20 at 07:06
  • 1
    It happens :) Good luck! – Alex Brohshtut Apr 02 '20 at 07:07

1 Answers1

1

OK, So, I'm posting myself the answer.

What @AlexBrohshtut spotted was right. Fat-arrow functions were an issue.

However, the most important part is that I hadn't put my function in methods (I had them in data section too). Pff...

So, this works:

<html>
    <head>
        <link rel="stylesheet" href="index.css">
        <script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
    </head>
    <body>

        <div id="app">
            {{ message }}
            This is another thing: <b>{{thing}}</b><br>
            <span :title="title" @click="doSomething">NO TITLE</span>
            <ul v-for="item in items">
                <li>{{item}}</li>
            </ul>
            <button @click="buttonClicked">{{toggleMessage}}</button>
            <label v-if="labelVisible">This is my label</label>
        </div>
    </body>
    <script>
        var app = new Vue({ 
            el: '#app',
            data: {
                message: 'Hello Vue!',
                thing: 'thing',
                title: "This is the title",
                doSomething: ()=>{
                    alert("did something")
                },
                items: ["one", "two", "three"],
                labelVisible: true,
                toggleMessage: "Hide Label",

            },
            methods: {
                buttonClicked: function() {
                    console.log("button");
                    this.labelVisible = !this.labelVisible;
                    console.log(this.labelVisible);
                    if (this.labelVisible) {
                        this.toggleMessage = "Hide Label";
                    }
                    else {
                        this.toggleMessage = "Show Label";
                    }
                    console.log(this.toggleMessage);
                }
            }
        });
    </script>
</html>
Dr.Kameleon
  • 22,532
  • 20
  • 115
  • 223