1

I Have a component which parse a json file on mounted phase.
The problem is :
when I click on a button , a send another GET method to get another json file and transmit it to my compoment.
the problem is that the component don't reload itself with the new props and my component display the old values
If someone know how to refresh components , here is my code

<template>
  <div class="perturbo">
    <div class="col-md-3 btnMenu">
      <button v-for="item,index in perturboButtonData.button_list" type="button"
              v-bind:style="'background:white'"
              class="btn-lg btn-block myBtnClass"
              @click="activeButton(index)">
        {{item.label}}
      </button>
    </div>
    <div class="col-md-9">
      <div class="row">
        <graphe
          v-for="ana,index in perturboData.ANA"
          :key="ana.id"
          :data="ana"
          :index="index"
          type="number"
          :timeSpec="perturboData.liste_dates">
        </graphe>
      </div>
      <div class="row">
        <graphe
          v-for="dig,index in perturboData.DIG"
          :key="dig.id"
          :index="index"
          :data="dig"
          type="number"
          isDigit="YES"
          :timeSpec="perturboData.liste_dates">
        </graphe>
      </div>
    </div>
  </div>
</template>



<script>
  import axios from 'axios'
  import Graphe from './Graphe/Graphe.vue'
  export default {
    name: 'perturbo',
    components : {
      'graphe' : Graphe
    },
    data: function () {
      return {
        isActivated: false,
        perturboData: {},
        perturboButtonData: {}
      }
    },
    methods: {
      activeButton : function (index) {
          console.log(this.perturboButtonData)
        axios.get('./static/cgi/' + this.perturboButtonData.button_list[index].link)
          .then((response) => {
            this.perturboData = response.data;
            this.isActivated = true

          })
      }
    },
    mounted : function () {
      axios.get('./static/cgi/format_json_perturbo.json')
        .then((response) => {
          this.perturboButtonData = response.data;
        })
    }
  }
</script>

Here is the code of my graphe component

<template>
  <div class="graphe">
        <vue-chart
          :chart-events="chartEvents"
          :columns="columns"
          :rows="rows"
          chart-type="LineChart"
          :options="options">
        </vue-chart>
  </div>
</template>



<script>
  export default {
    name: 'graphe',
    props: {
      data: {},
      timeSpec : Array,
      index: Number,
      type: String,
      isDigit:String,
    },
    data: function () {
      return {
        chartEvents: {
          'select': function() {

          },
          'ready': function() {
          }
        },
        rows: [],
        columns: [],
        options: {
          title: this.data.name,
          hAxis: {

          },
          vAxis: {
            ticks : []
          },
          width: 650,
          height: 350,
          curveType : 'function'
        }
      }
    },
    methods:  {
      normaliseData : function () {
        for (let i = 0; i < this.timeSpec.length; i++) {
          this.rows[i] = []
          this.rows[i][0] = parseFloat(this.timeSpec[i])
        }
        this.columns[0] = { 'type': 'number', 'label': 'time' }
        for (let i = 0; i < this.data.data.length; i++){
          this.columns[i+1] = {'type': this.type ,'label': this.data.data[i].name}
        }
        for (let i = 0; i < this.timeSpec.length; i++) {
          for (let y = 0; y < this.data.data.length; y++) {
            this.rows[i][y+1] = parseFloat(this.data.data[y].data[i])
          }
        }
        if (this.isDigit == "YES"){
          this.digRow(this.rows)
          for (let v = 0; v < this.data.data.length; v ++){
            this.options.vAxis.ticks[v] =  { v: v, f:  this.data.data[v].name}
          }
          this.options.curveType = ''
        }
      },
      digRow : function (rowTab) {

        let newRow = []
        let lengthMax = rowTab.length
        let rowTmp = []
        let index = 0

        for (let i = 0; i < lengthMax; i ++){
            rowTmp[index] = []
            rowTmp[index][0] = rowTab[i][0]
            for(let y = 1; y < rowTab[i].length; y ++){
              rowTmp[index][y] = rowTab[i][y] + y - 1
            }
            if (i + 1 !== rowTab.length)
            {

              newRow = rowTmp[index].slice()
              newRow[0] = rowTab[i+1][0]
              rowTmp.splice(index+1,0,newRow)
              index = index + 2
            }
        }
        this.rows = rowTmp
      }
    },
    mounted: function () {
//        // pour les colones
        this.normaliseData()
      }
  }
</script>

EDIT : I know where the problem is :
The data received from the parent is treated just once on the mounted function ! , that's why it doesn't reload on change
Should I use a watcher on props ? how can I do that

2
  • Show your actual code pls. namely perturboData and activeButton declarations. Commented Apr 26, 2017 at 13:53
  • @wostex I just updated with the two json I use Commented Apr 26, 2017 at 14:02

2 Answers 2

1

Instead of using a method to normalize the data, use a computed property for your rows, columns and options properties. This way, it will update automatically if any of the dependent properties change.

For example, your options property could be a computed property that looks like this:

computed: {
  options() {
    let options = {
      title: this.data.name,
      hAxis: {

      },
      vAxis: {
        ticks : []
      },
      width: 650,
      height: 350,
      curveType : 'function'
    };

    if (this.isDigit == "YES"){
      this.digRow(this.rows)
      for (let v = 0; v < this.data.data.length; v ++){
        options.vAxis.ticks[v] =  { v: v, f:  this.data.data[v].name}
      }
      options.curveType = ''
    }

    return options;
  }
}

Now, whenever this.data, this.isDigit, or this.rows changes, the options property will update as well.

Your rows and columns properties would look like this:

rows() {
  let rows = [];

  for (let i = 0; i < this.timeSpec.length; i++) {
    rows[i] = []
    rows[i][0] = parseFloat(this.timeSpec[i])

    for (let y = 0; y < this.data.data.length; y++) {
      rows[i][y+1] = parseFloat(this.data.data[y].data[i])
    }
  }

  return rows;
},
columns() {
  let columns = [];
  columns[0] = { 'type': 'number', 'label': 'time' }

  for (let i = 0; i < this.data.data.length; i++) {
    columns[i+1] = {'type': this.type ,'label': this.data.data[i].name}
  }

  return columns;
},
Sign up to request clarification or add additional context in comments.

1 Comment

thank you @thanksd you just answer my question and made me understand how computed var works !! :)
1

Your changed property won't force view update

To react to state changes, it’s usually better to use a computed property or watcher.

Try this variant

watch: {
    timeSpec(){
    //do something
    //this.normaliseData()
    }
}

Comments

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.