4

There is a v-select component and on change I am firing up fillData(selected) where selected is the v-model. And I need to update the label in datacollection.datasets.label on change. How do I do that ?

<script>
  import BarChart from './BarChart.js'
  import { mapGetters, mapActions } from "vuex";

  export default {
    name : "TestLegPerformance",
    components: {
      BarChart
    },
    data: () => ({   
      datacollection : {
          labels: ['Week-1','Week-2','Week-3'],
          datasets: [
            {
                label: '',
                backgroundColor: '#C58917',
                data: [40, 50, 20]
            }
          ]
        },
      selected: []

    }),
     computed: {
        ...mapGetters({
        planNames: "planNames"
        })
    },
    mounted () {
        this.getAllPlanNamesAction();
    },
    methods: {
      ...mapActions(["getAllPlanNamesAction"]), 
      fillData(selected){
          console.log(selected)
      },
    }
  }
</script>
acdcjunior
  • 132,397
  • 37
  • 331
  • 304
Jay Vignesh
  • 179
  • 2
  • 16

1 Answers1

8

Inside methods, you can reference to data properties using this.

In your case, you can use this.datacollection.datasets.label and assign to it:

methods: {
  // ...
  fillData(selected){
     this.datacollection.datasets[0].label = selected;
  },
}

Of course, this assuming that selected is the string you want to assign to the label.

Note: the this will only work when you declare the methods using methodName() {} (as you are) or methodName: function (){.... So don't use arrow functions when declaring vue methods, they will mess up your this.


Bind to events using @ (v-on) not : v-bind)

Your template:

<v-select label="Select a Plan" :items="planNames" v-model="selected" single-line max-height="auto" :change="fillData(selected)" required >

To listen to the change event, don't use:

:change="fillData(selected)"

use

@change="fillData"

Don't send an argument (it will mess things up). v-select will send you one already.

Notice the replacement of : with @.

The first, : is an alias to v-bind. So :change="xyz" is the same as v-bind:change="xyz".

The second, @ is an alias to v-on. So @change="xyz" is the same as v-on:change="xyz". which is what you want.

See demo JSFiddle here.


Updating label of vue-chartjs's BarChart automatically

Even though you are

The chart is not reflecting the changes (the label does not change) automatically.

I noticed this happens because the chart only reacts to whole datacollection changes, not to inner properties (like label).

So the solution is to:

  • "clone" datacollection
  • update the label of the clone
  • assign the clone to this.datacollection

And the chart will react (the label change will be reflected).

So, change your fillData method to the following:

fillData(selected){
    let collectionClone = Object.assign({}, this.datacollection);
    collectionClone.datasets[0].label = selected;
    this.datacollection = collectionClone;
},

Check here a working DEMO CODESANDBOX of this solution (see the changeLabelAndReassign() method of BarChart.vue).

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • Show your `v-select` – acdcjunior Feb 28 '18 at 12:26
  • Thank you but still the label won't change and reflect back in the UI – Jay Vignesh Feb 28 '18 at 12:41
  • Have a look at the demo JSFiddle. In that demo it reflects – acdcjunior Feb 28 '18 at 12:41
  • Thanks again and yeah when i put it directly into a div element it changes but what i am trying is to create a bar chart and I am now just trying to change the name based on select. – Jay Vignesh Feb 28 '18 at 12:46
  • Where is that `BarChart.js` from? Maybe the chart simply doesn't react to changes in the `.label` automatically. Maybe you have to call a `.setLabel('new label')` of some sort to change the label. – acdcjunior Feb 28 '18 at 12:49
  • I am using VueChart.js and i have a seperate barchart.js This is the barchart.js. import { Bar, mixins } from 'vue-chartjs' const { reactiveProp } = mixins export default { extends: Bar, mixins: [reactiveProp], props: ['options'], mounted () { // this.chartData is created in the mixin. // If you want to pass options please create a local options object this.renderChart(this.chartData, this.options) } } – Jay Vignesh Feb 28 '18 at 12:50
  • Show your ` – acdcjunior Feb 28 '18 at 13:00
  • The chart may not be reactive after all !! – Jay Vignesh Feb 28 '18 at 13:14
  • Yeah, I'm testing here and it doesnt seem to be: https://codepen.io/acdcjunior/pen/bLOOBe – acdcjunior Feb 28 '18 at 13:16
  • Also, I made a mistake: the correct is `@change="fillData"`, not `@change="fillData(selected)"`. And also `dataset` is an array: the correct would be `this.datacollection.datasets[0].label = selected;` not `this.datacollection.datasets.label = selected;`. I have updated the question and demo fiddle to fix this. – acdcjunior Feb 28 '18 at 13:18
  • Oh let me check that out. Really appreciate the help. Is the label changing now ? – Jay Vignesh Feb 28 '18 at 13:20
  • The label is getting changed but i have to click on the part in the UI where label is there and only then the change is reflected – Jay Vignesh Feb 28 '18 at 13:26
  • By "getting changed" you mean in the chart as well? – acdcjunior Feb 28 '18 at 13:28
  • I didn't make changes to the chart part. only the label. The label is changed even in your fiddle once you click on the label where it says 'data one' and changes to 'stuff' once you click on it . Check it out. – Jay Vignesh Feb 28 '18 at 13:29
  • Yeah, but I noticed it does not change in the chart. But I think I know why. It seems you can't just update a `label`, you have to re-set the whole `datacollection` for the chart to react to it. I'm testing this theory now – acdcjunior Feb 28 '18 at 13:35
  • yeah exactly !! Fill me in man !! Thank you so much for the help !! Appreciate it – Jay Vignesh Feb 28 '18 at 13:36
  • I believe I got it working. Check the updated answer. – acdcjunior Feb 28 '18 at 14:08