1

i'm trying to pass props from api call to a child a component but its not working atm, when i console log the data in my child it return a proxy object with the correct data. but i'm unable to use it inside the defaultData computed method in my child component where i want to used it

parent component

<template>
  <CRow>
    <CCol :md="6" class="mb-4">
      <CCard>
        <CCardHeader>Grafik Pie Hama</CCardHeader>
        <CCardBody><CChartPieExample :labels="labels"/></CCardBody>
      </CCard>
    </CCol>
  </CRow>
</template>

<script>
import * as Charts from './index.js'
import axios from 'axios'

export default {
  name: 'Charts',
  components: {
    ...Charts,
  },
  data() {
    return {
      labels: [],
    }
  },
  methods: {
    async getData() {
      let formdata = new FormData();
      formdata.append("work_location", "1");
      formdata.append("date_from", "2020-01-01");
      formdata.append("date_to", "2021-12-28");
      formdata.append("id_customer", "3");
      formdata.append("id_customer_location", "0");
      const headers = {
        'Authorization': '1cf34c57882bf600d69d9828ee639232KVpR0'
      }
      try {
        await axios.post("https://dev.cleancity.id/api/home/ListResultReportBinatang", formdata, {headers: headers}).then(res => {
          res.data.response.data.map((item) => {
            this.labels.push(item.name_animal)
          })
        });
        
      } catch (error) {
        console.log(error)
      }
    },
  },
  created() {
    this.getData()
  },
}
</script>

child component

<template>
  <CChartPie :data="defaultData"/>
</template>

<script>
import { CChartPie } from '@coreui/vue-chartjs'
export default {
  name: 'CChartPieExample',
  components: { CChartPie },
  props: ['labels'],

  computed: {
    
    defaultData() {
      
      return {
        labels: this.labels,
        datasets: [
          {
            backgroundColor: ['#41B883', '#E46651', '#00D8FF', '#DD1B16'],
            data: [40, 20, 80, 10],
          },
        ],
      }
    },
  },
  created() {
    // this return proxy object, but unable to use this above in defaultData
      console.log(this.labels)

  },
  
}
</script>

UPDATE: i've tried using the watch method to watch for change for my labels, now the labels showed up on initial load but after i refresh the page / move to another page the labels dissapeared

updated child component

<template>
  <CChartPie :data="defaultData"/>
</template>

<script>
import { CChartPie } from '@coreui/vue-chartjs'
export default {
  name: 'CChartPieExample',
  components: { CChartPie },
  props: ['labels', 'values'],
  data() {
    return {
      labelsLocal: this.labels,
    };
  },

  watch: {
    labels(val, oldVal) {
      console.log(val)
      if (val !== oldVal) this.labelsLocal = val
    }
  },

  computed: {
    defaultData() {
      
      return {
        labels: this.labelsLocal,
        datasets: [
          {
            backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850", "#734222", "#A52019", "#8A9597", "#DE4C8A", "#F44611", "#999950", "#C51D34", "#382C1E", "#CAC4B0", "#A2231D"],
            data: [40, 20, 80, 10, 10],
          },
        ],
      }
    },
  },

  mounted(){
    console.log(this.labels)
  },
  
}
</script>

Mike
  • 83
  • 3
  • 4
  • 11
  • I think that you should use a deep watch in your child component. https://stackoverflow.com/questions/41135188/vue-deep-watching-an-array-of-objects-and-calculating-the-change – miorey Jan 20 '22 at 21:57

2 Answers2

0

You can use watch feature to update the default data.

export default {
    data(){
        return {
            defaultData: {
            }
        }
    }
    watch: {
        labels(newVal, oldVal) {
            this.defaultData = {
                labels: this.labels,
                datasets: [...]
            }
        }
    }
}
Jian Zhong
  • 451
  • 3
  • 10
0

Did you tried to use vm.$watch API?

parent component:

data() {
  return {
    labels: [],
  }
},
methods: {
  async getData() {
     const payload = this.toFormData({
      work_location: '1',
      date_from: "2020-01-01",
      date_to: "2021-12-28",
      id_customer: "3",
      id_customer_location: "0"
    })
    const headers = {
      'Authorization': '1cf34c57882bf600d69d9828ee639232KVpR0'
    }
    try {
      await axios.post("https://dev.cleancity.id/api/home/ListResultReportBinatang", payload, {headers: headers}).then(res => {
        this.labels = res.data.response.data.map(item => item.name_animal)
      });
      
    } catch (error) {
      console.log(error)
    }
  },
  toFormData(rawParams) {
    const params = new FormData()
    if (!this.isObject(rawParams)) return params
  
    const keys = Object.keys(rawParams)
    keys.forEach(key => {
      rawParams[key] !== undefined && params.append(key, rawParams[key])
    })
  
    return params
  },
  isObject(obj) {
    return obj !== null && typeof obj === 'object'
  }
},
mounted() {
  this.getData()
},

child component

data() {
  return {
    defaultData: {
      labels: [],
      datasets: [
        {
          backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850", "#734222", "#A52019", "#8A9597", "#DE4C8A", "#F44611", "#999950", "#C51D34", "#382C1E", "#CAC4B0", "#A2231D"],
          data: [40, 20, 80, 10, 10],
        },
      ],
    },
  };
},
mounted() {
  const unwatch = this.$watch('labels', function(val) {
    this.$set(this.defaultData, 'labels', val)
    unwatch()
  })
},

tony19
  • 125,647
  • 18
  • 229
  • 307
nart
  • 1,508
  • 2
  • 11
  • 24