Class doesn't get applied to element in VueJS

111 Views Asked by At

So I want to apply the class .testcolor to the div when testvalue is true and apply nothing when it's false.

When i add the getClass method to :class it doesn't even get called but it gets called when called from {{ getClass }}. I tried clearing the cache and even rewrote the entire code and it still doesnt work! Here is the full code:

<!DOCTYPE html>
<html>
    <head>
        <title>Vue Test</title>
        <style>
            .testcolor {
                color: red !important;
            }
        </style>
    </head>
    <body>
        <div id="test" :class="getClass">
            <h1>Test stuff</h1>
            <h2>{{ testvalue }}</h2>
        </div>
        <script type="module">
            import { createApp } from "https://unpkg.com/[email protected]/dist/vue.esm-browser.js";

            createApp({
                data() {
                    return {
                        testvalue: true,
                    };
                },
                methods: {
                    getClass() {
                        console.log("Method 'getClass' called");
                        return this.testvalue ? "testcolor" : "";
                    },
                },
            }).mount("#test");
        </script>
    </body>
</html>

I figured something out that if I mount the Vue instance on the div element and add the :class="testClass" (from the answer) to the h2 it works! But when I mount it on the h2 element now it doesn't work!

1

There are 1 best solutions below

3
Prashanth Puranik On

EDIT based on your comment @martin0300

Firstly, you need to wrap the division in another division whose id must be test. Vue does not consider the container element (div with id test) as part of the app and does not process any directives. Left a references below that mentions this.

https://vuejs.org/guide/essentials/application.html#mounting-the-app

So please change your markup to something like this for applying the value from getClass method...

<div id="test">
    <div :class="getClass()">
        <h1>Test stuff</h1>
        <h2>{{ testvalue }}</h2>
    </div>
</div>

...or this way for using the computed property approach (explained below.)

<div id="test">
    <div :class="testClass">
        <h1>Test stuff</h1>
        <h2>{{ testvalue }}</h2>
    </div>
</div>

--

Original message:

getClass when defined as a method needs to be called, and the returned value ("testcolor") is set as the value of :class. Note the function call getClass() in place of the getClass you used.

<div id="test" :class="getClass()">
    <h1>Test stuff</h1>
    <h2>{{ testvalue }}</h2>
</div>

That said, this is not the preferred way to apply classes conditionally. We prefer a computed property over of a method. A method is invoked on every render, whereas a computed property is recomputed only when the underlying reactive data it depends on changes (in this case the computed property testClass depends on the reactive property testvalue.

The idiomatic Vue code in your case would be the following. Note that computed properties are not invoked like functions since they are internally implemented using accessor methods / using a JS Proxy (:class="testClass" and NOT :class="testClass()"). I believe this difference between the way methods and computed properties are used is the cause of your confusion.

<div id="test" :class="testClass">
    <h1>Test stuff</h1>
    <h2>{{ testvalue }}</h2>
</div>
<script type="module">
    import { createApp } from "https://unpkg.com/[email protected]/dist/vue.esm-browser.js";

    createApp({
        data() {
            return {
                testvalue: true,
            };
        },
        computed: {
            testClass() {
                console.log("Recomputed testClass");
                return this.testvalue ? "testcolor" : "";
            },
        },
    }).mount("#test");
</script>