Vuetify Select with options array of objects prevents update from occurring?

198 Views Asked by At

I've got a doughnut chart being displayed using vue-chartjs and am supplying color schemes via chartjs-plugin-colorschemes.

I'm working on the ability for the user to switch out color schemes and persist their chosen scheme to the db, however I've run into an odd issue. When adding a colors array to the options that are being supplied to the Vuetify select, it breaks the chart from updating to the new color scheme. I've narrowed it down to this specifically, because if I remove the colors array from options, it correctly updates the chart (however then I'm not able to display the colors like I'm trying to do in the select dropdown).

Why would adding properties to the Vuetify select break this functionality? Is it because they're being dynamically generated?

**ParentComponent.vue:**lang-vue

    <template>
      <div
        class="chart-wrapper">
        <child-graph
          v-resize="onResize"
          :chart-data="chartData"
          :is-mobile="isMobile"
          :styles="graphStyles"
          :theme="localTheme" />
      </div>
    
      <pack-theme-modal
        v-model="themeModalOpen"
        :theme="localTheme"
        @handle-update="handleUpdateTheme" />
    </template>
    
    <script>
      export default {
        data () {
          localTheme: '',
          themeModalOpen: false
        },
    
        methods: {
          handleUpdateTheme (theme) {
            this.localTheme = theme;
            this.themeModalOpen = false;
          }
        }
      }
    </script>

ChildGraph.vue:

    <script>
      import { Doughnut, mixins } from 'vue-chartjs';
      import Chart from 'chart.js';
      import 'chartjs-plugin-colorschemes';
      const { reactiveProp } = mixins;
    
      export default {
        extends: Doughnut,
    
        mixins: [reactiveProp],
    
        props: {
          theme: {
            type: String,
            default: ''
          }
        },
    
        data () {
          const vm = this;
          return {
            options: {
              cutoutPercentage: 75,
              legend: {
                display: true,
                position: 'right'
              },
              plugins: {
                colorschemes: {
                  scheme: this.theme
                }
              },
              responsive: true,
              maintainAspectRatio: false,
              tooltips: {
                enabled: false
              },
            }
          };
        },
    
        mounted () {
          this.renderChart(this.chartData, this.options);
        },
    
        watch: {
          theme (newVal, oldVal) {
            console.log({ newVal });
            const chart = this.$data._chart;
            chart.options.plugins.colorschemes.scheme = newVal;
            chart.update();
          }
        }
      };
    </script>

ThemeModal.vue:

<template>
  <v-dialog
    v-model="show"
    max-width="750">
    <v-card>
      <v-card-title>
        Choose a New Chart Color Theme
      </v-card-title>
      <v-card-text>
        <v-container>
          <v-row>
            <v-col cols="12">
              <v-select
                v-model="localTheme"
                color="primary"
                dense
                item-text="text"
                item-value="value"
                :items="options"
                label="Theme Options"
                outlined>
                <template #selection="{ item }">
                  <p class="mb-0 mr-4 text-body-1">
                    {{ item.text }}
                  </p>
                  <color-swatch :colors="item.colors" />
                </template>
                <template #item="{ item, attrs, on }">
                  <v-list-item
                    v-bind="attrs"
                    v-on="on">
                    <v-list-item-content>
                      <v-list-item-title>
                        <span class="mr-4">{{ item.text }}</span>
                        <color-swatch :colors="item.colors" />
                      </v-list-item-title>
                    </v-list-item-content>
                  </v-list-item>
                </template>
              </v-select>
            </v-col>
          </v-row>
        </v-container>
      </v-card-text>
      <v-card-actions class="justify-space-between">
        <v-btn
          class="grey7--text"
          :ripple="false"
          text
          @click="closeModal">
          Cancel
        </v-btn>
        <v-btn
          color="primary"
          depressed
          :ripple="false"
          @click="handleUpdate">
          <span>Update Theme</span>
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script>
  import 'chartjs-plugin-colorschemes/src/plugins/plugin.colorschemes';
  import { Blue6, BlueGreen6, Breeze6, Celestial6, Circuit6, Damask6, Depth6, Flow6, Forte6, Genesis6, IonBoardroom6, Kilter6 } from 'chartjs-plugin-colorschemes/src/colorschemes/colorschemes.office';
  import { Tableau10, ColorBlind10, JewelBright9, HueCircle19 } from 'chartjs-plugin-colorschemes/src/colorschemes/colorschemes.tableau';
  import ColorSwatch from '~/components/ColorSwatch.vue';

  export default {
    props: {
      theme: {
        type: String,
        default: ''
      },
      value: {
        type: Boolean,
        default: false
      }
    },

    data () {
      return {
        localTheme: this.theme || 'tableau.Tableau10',
        options: [
          // COMMENTED OUT OPTIONS WORK, BUT DON'T DISPLAY COLOR SWATCH
          // { text: 'Theme 1', value: 'office.Blue6' },
          // { text: 'Theme 2', value: 'office.BlueGreen6' },
          // { text: 'Theme 3', value: 'office.Breeze6' },
          // { text: 'Theme 4', value: 'office.Celestial6' },
          // { text: 'Theme 5', value: 'office.Circuit6' },
          // { text: 'Theme 6', value: 'office.Damask6' },
          // { text: 'Theme 7', value: 'office.Depth6' },
          // { text: 'Theme 8', value: 'office.Flow6' },
          // { text: 'Theme 9', value: 'office.Forte6' },
          // { text: 'Theme 10', value: 'office.Genesis6' },
          // { text: 'Theme 11', value: 'office.IonBoardroom6' },
          // { text: 'Theme 12', value: 'office.Kilter6' },
          // { text: 'Theme 13', value: 'tableau.Tableau10' },
          // { text: 'Theme 14', value: 'tableau.ColorBlind10' },
          // { text: 'Theme 15', value: 'tableau.JewelBright9' },
          // { text: 'Theme 16', value: 'tableau.HueCircle19' }

          // COMMMENTED IN OPTIONS SHOW COLOR SWATCH BUT DON'T UPDATE GRAPH
          { text: 'Theme 1', value: 'office.Blue6', colors: Blue6.map(color => color) },
          { text: 'Theme 2', value: 'office.BlueGreen6', colors: BlueGreen6.map(color => color) },
          { text: 'Theme 3', value: 'office.Breeze6', colors: Breeze6.map(color => color) },
          { text: 'Theme 4', value: 'office.Celestial6', colors: Celestial6.map(color => color) },
          { text: 'Theme 5', value: 'office.Circuit6', colors: Circuit6.map(color => color) },
          { text: 'Theme 6', value: 'office.Damask6', colors: Damask6.map(color => color) },
          { text: 'Theme 7', value: 'office.Depth6', colors: Depth6.map(color => color) },
          { text: 'Theme 8', value: 'office.Flow6', colors: Flow6.map(color => color) },
          { text: 'Theme 9', value: 'office.Forte6', colors: Forte6.map(color => color) },
          { text: 'Theme 10', value: 'office.Genesis6', colors: Genesis6.map(color => color) },
          { text: 'Theme 11', value: 'office.IonBoardroom6', colors: IonBoardroom6.map(color => color) },
          { text: 'Theme 12', value: 'office.Kilter6', colors: Kilter6.map(color => color) },
          { text: 'Theme 13', value: 'tableau.Tableau10', colors: Tableau10.map(color => color) },
          { text: 'Theme 14', value: 'tableau.ColorBlind10', colors: ColorBlind10.map(color => color) },
          { text: 'Theme 15', value: 'tableau.JewelBright9', colors: JewelBright9.map(color => color) },
          { text: 'Theme 16', value: 'tableau.HueCircle19', colors: HueCircle19.map(color => color) }
        ]
      };
    },

    computed: {
      show: {
        get () {
          return this.value;
        },
        set (value) {
          this.$emit('input', value);
        }
      }
    },

    methods: {
      closeModal () {
        this.show = false;
      },
      handleUpdate () {
        this.$emit('handle-update', this.localTheme);
      }
    },

    watch: {
      theme (val) {
        this.localTheme = val;
      }
    },

    components: {
      ColorSwatch
    }
  };
</script>

1

There are 1 best solutions below

0
On BEST ANSWER

On a Hail Mary attempt, I found something in the chartjs-plugin-colorschemes docs that mentioned setting override: true within the color schemes object on data. Adding that fixed it somehow!

plugins: {
  colorschemes: {
    scheme: this.theme,
    override: true
  }
},