Search code examples
javascriptvue.jsvuejs3primevue

PrimeVue theme change


Apparently, in the last few PrimeVue updates there has been a PrimeVue.changeTheme() method that I would very much like to use. The documentation says that two things are required.

  1. copying the selected themes from the PrimeVue resources/themes folder and placing them under the public folder.
  2. In the index.html file, create links to these styles along with giving them an ID so that this ID is later passed to the function.

So that's what I did but the solution doesn't quite work, perhaps I'm misunderstanding something. Link to docs: https://v3.primevue.org/theming/

index.html file:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <link id="lara-dark-purple-link" rel="stylesheet" href="/themes/lara-dark- 
    purple/theme.css">
    <link id="lara-light-purple-link" rel="stylesheet" href="/themes/lara-light- 
    purple/theme.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

Here is code from component which hold buttons with theme changing:

<script setup>
import { onMounted } from 'vue';
import { usePrimeVue } from 'primevue/config';

const PrimeVue  = usePrimeVue();
const toggleDarkMode = () => {
  PrimeVue.changeTheme('lara-dark-purple', 'lara-dark-purple', 'lara-dark-purple-link', () => {});    
}
const toggleLightMode = () => {
  PrimeVue.changeTheme('lara-light-purple', 'lara-light-purple', 'lara-light-purple-link', () => {});
}
</script>

My folder structure:

Folder structure


Solution

  • Your solution is almost correct. You just didn't understand the use of the <link> id, but no problem, let me quickly summarize it for you:

    1.) Need a new reference element to theme css file.

    Second part is making the theme.css accessible via a link element...

    <!-- Add default theme url to href | now default is light -->
    <link id="id-to-link" rel="stylesheet" href="/themes/lara-light-purple/theme.css">
    

    2.) Use your-id in function as 3rd parameter.

    ...so that the id of the link can be provided as the 3rd parameter to the changeTheme function.

    // if current theme is dark
    const selectLightTheme = () => {
        // 1. Current theme name
        // 2. Next theme name
        // 3. id of <link>, what reference to where set theme css file
        PrimeVue.changeTheme('lara-dark-purple', 'lara-light-purple', 'id-to-link', () => {});    
    }
    
    // if current theme is light
    const selectDarkTheme = () => {
        // 1. Current theme name
        // 2. Next theme name
        // 3. id of <link>, what reference to where set theme css file
        PrimeVue.changeTheme('lara-light-purple', 'lara-dark-purple', 'id-to-link', () => {});
    }
    

    Source from documentation: https://v3.primevue.org/theming/

    How to make dynamically?

    <!-- Add default theme url to href | now default is light -->
    <link id="id-to-link" rel="stylesheet" href="/themes/lara-light-purple/theme.css">
    
    import { ref } from 'vue';
    import { usePrimeVue } from 'primevue/config';
    
    // set default theme folder-name to currentTheme
    const currentTheme = ref('lara-light-purple'); // lara-light-purple or lara-dark-purple (1st parameter)
    
    const PrimeVue = usePrimeVue();
    
    // change current theme to next
    const toggleTheme = () => {
        // What is next theme? (2nd parameter)
        let nextTheme = 'lara-light-purple';
        if (currentTheme.value === 'lara-light-purple') nextTheme = 'lara-dark-purple';
        else if (currentTheme.value === 'lara-dark-purple') nextTheme = 'lara-light-purple';
    
        // 1. Current theme name
        // 2. Next theme name
        // 3. id of <link>, what reference to where set theme css file --> fix, single id to <link>
        PrimeVue.changeTheme(currentTheme.value, nextTheme, 'id-to-link', () => {});    
    
        // So current theme now:
        currentTheme.value = nextTheme;
    }
    

    CDN Live Example

    // CDN Vue Import
    const { createApp, ref } = Vue
    
    const app = createApp({
      setup() {
        // set default theme folder-name to currentTheme
        const currentTheme = ref('lara-light-purple'); // lara-light-purple or lara-dark-purple (1st parameter)
    
        // const PrimeVue = usePrimeVue(); // If I were not using CDN, my PrimeVue variable would not exist yet. In that case, I would need to declare it with the usePrimeVue() function loaded from primevue/config
    
        // change current theme to next
        const toggleTheme = () => {
          // What is next theme? (2nd parameter)
          let nextTheme = 'lara-light-purple';
          if (currentTheme.value === 'lara-light-purple') nextTheme = 'lara-dark-purple';
          else if (currentTheme.value === 'lara-dark-purple') nextTheme = 'lara-light-purple';
    
          // PrimeVue.changeTheme('lara-light-purple', 'lara-dark-purple', 'id-to-link', () => {});
          // --> The usePrimeVue() function is not available in the CDN version, so I am currently implementing a native JS solution in place of changeTheme (the only additional task is to ensure the FULL URL for both templates)
          // Native JS Solution:
          document.getElementById('id-to-link').href = `https://cdn.jsdelivr.net/npm/[email protected]/resources/themes/${nextTheme}/theme.css`
    
          // So current theme now:
          currentTheme.value = nextTheme;
        }
    
        return { toggleTheme }
      },
      components: {
        "Button": primevue.button,
      },
      template: `
        <Button label="Click to Toggle Theme" @click="toggleTheme" />
      `
    }).mount('#app')
    <!-- Core Vue -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.prod.js"></script>
    
    <!-- Core Primevue -->
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/resources/primevue.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/core/core.min.js"></script>
    
    <!-- Add default theme url to href | now default is light -->
    <link id="id-to-link" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/resources/themes/lara-light-purple/theme.css">
    
    <!-- App -->
    <div id="app"></div>