What is the best way to modify the :class name in a view file using a component in Vue?

I am currently facing an issue with implementing two active themes, a light-theme and a dark-theme, within an external button component. I have been successful in making it work by embedding the code and function directly inside the view.

While this setup works as an example, I have encountered a "real world" scenario where I need the functionality to switch between dark and light mode to be operational from within the component itself, dynamically changing the class based on the selected theme.

In my "Home.vue" file, I import components ButtonA and ButtomB:

<template>
  <div :class="theme" class="bg-background-primary">
    <h1 class="text-4xl text-typo-primary">Test title</h1>

    <!-- Inside Home.vue - WORKING -->
    <button class="border border-gray-400 bg-blue-500 hover:bg-blue-700 text-white p-2 rounded" @click="toggleThemeOne()">Toggle Dark/Light</button>
    <!-- Component with function outside - WORKING -->
    <ButtonA msg="From component" @click.native="toggleThemeTwo()" />
    <ButtonB msg="Full from component" />
  </div>
</template>

<script>


import ButtonA from '@/components/ButtonA.vue'
import ButtonB from '@/components/ButtonB.vue'

export default {
  name: 'Home',
  components: {
    ButtonA,
    ButtonB
  },
  data() {
    return {
      theme: 'theme-light',
    }
  },
  methods: {
    toggleThemeOne() {
      this.theme = this.theme === 'theme-light' ? 'theme-dark' : 'theme-light'
      localStorage.setItem('theme', this.theme)
      console.log('toggleThemeOne working');
      console.log(this.theme)
    },
    toggleThemeTwo() {
      this.theme = this.theme === 'theme-light' ? 'theme-dark' : 'theme-light'
      localStorage.setItem('theme', this.theme)
      console.log('toggleThemeTwo working');
      console.log(this.theme)
    },
  }
}
</script>

Home.vue has a functional button for switching themes

ButtonA

It contains only HTML with the function included in the component

<template>
    <div>
        <button class="border border-gray-400 bg-blue-500 hover:bg-blue-700 text-white p-2 rounded"> {{ msg }} </button>
    </div>
</template>

<script>
export default {
    name: "ButtonComp",
    props: [
        'msg'
    ]
}
</script>

ButtonB

<template>
    <div>
        <button
            class="border border-gray-400 bg-blue-500 hover:bg-blue-700 text-white p-2 rounded"
            @click="toggleThemeTree()"
        > {{ msg }} </button>
    </div>
</template>

<script>
export default {
    name: "ButtonComp",
    props: [
        'msg'
    ],
    methods: {
        toggleThemeTree() {
            this.theme = this.theme === 'theme-light' ? 'theme-dark' : 'theme-light'
            localStorage.setItem('theme', this.theme)
            console.log('toggleThemeTree working');
            console.log(this.theme)
        },
    },
}
</script>

This is the button that is causing issues. The function should update the :class property in Home.vue, but I can only see the values in the console and the :class is not functioning as expected.

I have previously attempted using $emit and computed properties, but unfortunately, these solutions did not yield the desired results.

Answer №1

To properly pass the theme to ButtonB component in Home.vue, follow these steps:

<ButtonB msg="From full component" :theme.sync="theme" />

Next, ensure that in the ButtonB component, you emit the value back to the parent when clicked:

<script>
export default {
    name: "ButtonComp",
    props: [
        'msg',
        'theme'
    ],
    methods: {
        toggleThemeTree() {
            let theme = this.theme === 'theme-light' ? 'theme-dark' : 'theme-light' // Avoid directly changing this.theme
            localStorage.setItem('theme', theme)
            this.$emit('update:theme', theme)
        },
    },
}
</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to showcase content without triggering a file download during a GET Request?

I recently created a webpage that showcases API responses in a neat tabular format. The technologies I used for this project were Angular JS, Servlets, and Java-Rest Assured framework. Each entry in the table includes a link to a log file, which is provid ...

Simplified method of connecting dynamic components without needing to remember functions in jQuery

I have a page where users can freely move, resize, and modify content. The basic setup is as follows: $('.element').on().resizable().draggable(); When this code is called on page load, it allows elements to be resizable and draggable. The issu ...

Adding a new element with Jquery when a dropdown option is selected

What is causing this issue to not function properly? <script> $(document).ready(function(){ $('#custom_field option').click(function(){ $('#custom_field_input').append('<tr><td></td> ...

Utilizing the power of Ajax for enhancing table sorting and filtering functionality

Having an issue using JQuery tablesorter to paginate a table with rows fetched from the database. //list players by points (default listing) $result=mysql_query("select * from players order by pts_total") or die(mysql_error()); echo "<table id='li ...

The React DOM isn't updating even after the array property state has changed

This particular issue may be a common one for most, but I have exhausted all my options and that's why I am seeking help here. Within my React application, I have a functional component named App. The App component begins as follows: function App() ...

What is causing my fetch response to not be passed through my dispatch function?

I'm currently utilizing a node server to act as the middleman between firebase and my react native app. Could someone kindly point out what might be going awry in my fetch method below? export const fetchPostsByNewest = () => { return (dispatch ...

Having trouble displaying the desired formatting when mapping through nested JSON in Node ES6

Currently working on a project to build a photo gallery using nested JSON data. My goal is to iterate through the data and create a well-structured JavaScript object or a smaller JSON file that includes only the text and image URL nodes. However, my curren ...

Slightly puzzled by the declaration of `var app = express()`

After going over the documentation, I'm still struggling to grasp why we store express() inside an app variable. I attempted to call methods using express().get and .post directly, but was unsuccessful. Why is that? Why doesn't it function in t ...

Convert a JavaScript object into a serialized form

Alright, so here's the thing that's been bugging me. I have this JavaScript object that I need to pass to a PHP script using jQuery AJAX. But every time I try to pass it as is, I get an error. It seems like the object needs to be serialized befor ...

The functionality of jQuery's toggleClass is not functioning properly when clicking on a different thumbnail

My objective: I want to display a set of thumbnails. When a thumbnail is clicked, I want to toggle the hiddenElement class and show a large image inside a hidden div. If anywhere in the DOM is clicked, it should hide the current image or allow the user t ...

Exploring the features of React.js version 16

I'm confused about what {...props} does. I know it makes passing props easier, but what happens if there are no props to begin with? Take this example: const input = (props) => { let inputElement = null; switch(props.inputtype) { ...

Steps to implement jQuery after executing the command "npm install jquery"

Greetings! I recently utilized npm install jquery to add jQuery to my project. However, I noticed that it was downloaded into node_modules\jquery along with some unnecessary files. My goal is to only move node_modules\jquery\dist\jquer ...

Is there a way to dynamically change the helperText of a Material UI TextField using its current value through code?

I'm currently attempting to dynamically change the helperText of a Material UI TextField based on the value entered into the field. Below is my current implementation: const defaultScores = { STR: 10, DEX: 10, CON: 10, INT: 10, WIS: 10, CH ...

Color the column of our kendo ui grid in gray

Within this kendo ui grid here, the initial column [OrderID] cannot be modified. I am seeking a solution to visually distinguish all disabled columns by applying a subtle gray shade, allowing users to easily identify them as non-editable. ...

Unable to access current props within useEffect block

When I use useEffect with the parameter props.quizStep, my function fn (which is a keydown event listener) is unable to access the current value of props.quizStep. I'm puzzled as to why it's not working properly. Can you help me understand? Bel ...

Guide to spinning a CannonJS RigidBody

Has anyone found a way to rotate a CANNON.RigidBody object in CannonJS (the physics library)? I'm attempting to align the object's rotation with that of the camera, so they both face the same direction. I understand that I need to adjust the quat ...

Exploring the differences between io.emit and socket.emit

Having just delved into the world of socket.io, I've come across something that's puzzling me. I'm unclear on the distinction between socket.emit and io.emit, and my search for a clear explanation has turned up empty. io.on('connection ...

Creating Circular Trails during Animation in D3.js

Currently, I am creating circles with each update that smoothly transition from one position to another. Below is the code snippet I am utilizing... function drawChart(newData) { var circles = slider.selectAll(".dot") .data(newData); circl ...

Choosing multiple images using JavaScript/jQuery

Gridster is being used for a webpage, with widgets containing images that can be added and deleted using the "+" and "X" buttons. Current Status Clicking the "+" button opens a modal where multiple images can be selected and added to the widgets by click ...

Instructions for adding an onfocus event listener to an input field in order to dynamically change the formatting of associated labels

I'm looking to change the style of my input labels to a more fancy look by implementing the .fancyclass style when using the onfocus event on the input field. I am curious to know how this can be achieved through event listeners in Javascript? ...