0
votes

I have a Navigation component with a button to toggle dark mode/light mode. When I click this button, I would like to change a class in the App.vue. How to pass the data from the button to the App.vue? I believe I have to emit something from the Top Nav and v-bind the class in App.vue, but I don't quite understand how to get it change the class.

When I run this, the button does not change the class on the div.

App.vue

<template>
  <div id="app" :class="[isActive ? 'darkmode' : '']>
    <header>
      <top-nav @change-mode="enableDarkMode"></top-nav>
    </header>
    ...
  </div>
</template>

<script>

export default {
  name: "App",
  components: {
    TopNav,
  },
  props: ['isActive'],
  data() {},
  methods: {
    enableDarkMode(isActive) {
      console.log(isActive)
    },
  },
};
</script>

Top Nav Component

<template>
  ...
  <div>
    <button
      :class="[isActive ? 'dark' : 'light']"
      @click="toggle">
        {{ isActive ? "DarkMode" : "LightMode" }}
    </button>
  </div>
</template>

<script>
export default {
  name: "TopNav",
  data() {
    return {
      isActive: false,
    };
  },
  components: {},
  methods: {
    toggle() {
      this.isActive = !this.isActive;
      this.$emit('change-mode', this.isActive )
      console.log('emit child')
    },
  },
};
</script>
1

1 Answers

0
votes

From the snippet you provided it seems like the App.vue has isActive props instead of data for the method enableDarkMode to manage. Vue's props is not to be updated by the component they belong to because of how the data flow works in Vue props. With the App.vue being the parent of Top Nav component, you probably want it to be like this:

App.vue

<template>
  <div id="app" :class="[isActive ? 'darkmode' : '']>
    <header>
      <top-nav @change-mode="enableDarkMode"></top-nav>
    </header>
    ...
  </div>
</template>

<script>

export default {
  name: "App",
  components: {
    TopNav,
  },
  // this is probably not needed because App.vue is the parent component
  // props: ['isActive'],
  data() {
    return {
      isActive: false,
    };
  },
  methods: {
    enableDarkMode(isActive) {
      // manages the data
      this.isActive = isActive;
    },
  },
};
</script>

Top Nav component

<template>
  ...
  <div>
    <button
      :class="[isActive ? 'dark' : 'light']"
      @click="toggle">
        {{ isActive ? "DarkMode" : "LightMode" }}
    </button>
  </div>
</template>

<script>
export default {
  name: "TopNav",
  data() {
    return {
      isActive: false,
    };
  },
  components: {},
  methods: {
    toggle() {
      this.isActive = !this.isActive;
      this.$emit('change-mode', this.isActive )
      console.log('emit child')
    },
  },
};
</script>