0

I have created three themes, light, default and dark. I'm now trying to create a toggle in the footer so I can switch between each theme.

With the advice of @jogarcia I have changed my code to the following.

The mixin is now in its own file called themes.js

export default {
  data() {
    return {
      currentTheme: "",
    };
  },
  mounted() {
    const storedTheme = localStorage.getItem("theme-colour");
    if (!storedTheme) {
      this.currentTheme = "theme-default";
    } else {
      this.currentTheme = localStorage.getItem("theme-colour");
    }
  },
  methods: {
    toggleTheme() {
      const storedTheme = localStorage.getItem("theme-colour");
      if (!storedTheme) {
        localStorage.setItem("theme-colour", "theme-light");
        this.currentTheme = localStorage.getItem("theme-colour");
      }
      if (storedTheme === "theme-default") {
        localStorage.setItem("theme-colour", "theme-light");
        this.currentTheme = localStorage.getItem("theme-colour");
      } else {
        localStorage.setItem("theme-colour", "theme-dark");
        this.currentTheme = localStorage.getItem("theme-colour");
      }
    },
  },
};

Therefore I have imported the file in both the app.vue and Footer component by doing import themes from "@/mixins/themes"; and mixins: [themes] in the export respectively.

I have also added :class="currentTheme" to the app.vue file.

However, I'm still running into a few more issues.

  1. How do I get the theme class to change dynamically?

Here is a gif of what I mean, as you can see I can toggle, the value is being changed in localStorage but the class name isn't changing in the main app div.

https://i.gyazo.com/2044ff9293328aaaae8810272ffc6a5a.mp4

Update:

I've updated the bind in app.vue to :class="[currentTheme]" but this still doesn't work.

Here is a new GIF https://i.gyazo.com/2f1d6a98b51e2d00c8ba748940016f55.mp4

As you can see the default theme loads by default which is now correct, however, when I toggle to dark the data currentTheme doesn't change. It only changes on refresh because of localstorage and I can't select the theme in the dropdown using Vue devtools if that's any issue as well.

App.vue

<template>
  <div
    id="app"
    class="flex flex-col min-h-screen h-full font-sans text-copy-primary leading-normal tracking-wide overflow-x-hidden"
    :class="[currentTheme]"
  >
    <Navigation />
    <DealBanner discountValue="20" date="April 26, 2020 12:00" discountCode="RELEASE" />
    <router-view class="flex-1" />
    <Footer />
  </div>
</template>

<script>
import themes from "@/mixins/themes";
import Navigation from "@/components/Navigation";
import DealBanner from "@/components/DealBanner";
import Footer from "@/components/Footer";

export default {
  name: "App",
  components: {
    Navigation,
    DealBanner,
    Footer
  },
  mixins: [themes]
};
</script>

Footer.vue (shorted)

<template>
  <footer
    class="px-6 xl:px-0 py-6 bg-theme-primary text-copy-primary border-t border-theme-ternary"
  >
    <div class="flex flex-col justify-between lg:flex-row lg:items-center xl:px-
      <div class="text-center">
        <p>Theme Switcher</p>
        <div @click="toggleTheme">Toggle</div>
        {{currentTheme}}
      </div>
    </div>
  </footer>
</template>

<script>
import themes from "@/mixins/themes";
export default {
  name: "Footer",
  mixins: [themes]
};
</script>
...
7
  • What issue are you having here? Commented Apr 18, 2020 at 13:51
  • I get error 'toggleThemeMixin' is not defined Commented Apr 18, 2020 at 13:53
  • 1
    ok, then put the mixin code in footer component only, or if you want it to have access in all components then create a global mixin. Commented Apr 18, 2020 at 13:56
  • I want the switcher to be in the footer but I need it to change the class in the main app div so that's why I thought a mixin would be the best choice and share it between components, so it needs to be shared between components. Commented Apr 18, 2020 at 13:58
  • I've created a global mixin but the toggle isn't working in the footer. I'll update the question @palaѕн Commented Apr 18, 2020 at 14:15

1 Answer 1

1

I see several problems in your mixin.

Local Storage.

Be sure that you are saving theme-color else you will get an error if is not in the local storage.

methods: {
    toggleTheme() {
      const storedTheme = localStorage.getItem("theme-colour");
      if (!storedTheme) {
        localStorage.setItem("theme-colour", "theme-light");
        this.currentTheme = "theme-dark";
      }
      if (storedTheme === "theme-light") {
        localStorage.setItem("theme-colour", "theme-light");
        this.currentTheme = "theme-dark";
      } else {
        localStorage.setItem("theme-colour", "theme-dark");
        this.currentTheme = "theme-light";
      }
    },
  },

Structure of the mixin

Am not sure if you are importing the mixin correctly or not so am going to add this here just in case. This is the way i make and import mixin, following the docs of course. If you are using the vue cli, the mixin should be on its own file, this way follows that idea.

mixin.js

export default {
  data() {},
  methods {}
}

AnyVueComponent.vue

<template>
...
</template>
<script>
  import mixin from 'path to my mixin';
  export default {
    ......
    mixins: [mixin]
    ......
  }
</script>

currentTheme variable reactivity

You don't have to keep loading from the localStorage you can save all the times but load just on mounted, kind of like this:

mixin.js

export default {
  data() {
    currentTheme: ''
  },
  mounted(){
    const storedTheme = localStorage.getItem("theme-colour");
    if (!storedTheme) {
      this.currentTheme = "theme-light"
    }else{
      this.currentTheme = localStorage.getItem("theme-colour");
    }
  },
  methods {...}
}

Using this way for class binding.

//Any format you want to do to currentTheme do it inside the computed
:class=[currentTheme]

Check this sandbox:

https://codesandbox.io/s/exciting-keller-nowok?file=/src/App.vue

Sign up to request clarification or add additional context in comments.

11 Comments

Thanks for the explanations, I've changed my code around a bit and I can see the toggling when I click the toggle button, localStorage is changing but I can't seem to set a default theme and the class doesn't change dynamically. I'll update the question.
Updated the question
@debugabug you just have to load one time , and save many, i changed my answer check it
I've swapped out the current code, for the new code but it's not switching dynamically. Here's a gif i.gyazo.com/81c65a5391c89512893260cba0da0606.mp4
@debugabug i made a little change at the end, that should work, if not update your post with the new errors
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.