João Saro
João Saro

Reputation: 543

Vue.js - update child component's function

I have a child component with a prop, but also there's is a mounted function to init date and hour. How to update this function when data from parent is reloaded?

Parent component:

 <template>
      <div>
        <ul>
          <li v-for="item in occurrences">
            {{ item.title }} {{ item.completed }}</small>
          </li>
        </ul>
        <sourceupd class="source" v-bind:source='source'></sourceupd>
      </div>
    </template>

    <script>
      import axios from 'axios'
      import sourceupd from './SourceAndUpdated'

      export default {

        name: 'Occurrences',

        components: {
          sourceupd
        },

        data: function () {
          return {
            occurrences: [],
            source: 'ANPC'
          }
        },

        mounted: function () {
          var _self = this

          function callAPI () {
            // call api code
          }

          callAPI()

          setInterval(() => {
            callAPI()
          }, 1024 * 3)
        }
      }
    </script>

Child Component:

<template lang="html">
    <small class="source-ref">Fonte: {{ source }} | Actualização:{{ updated.hour }}:{{ updated.minutes }}</small>
</template>

<script>
import moment from 'moment'

export default {
  data: function () {
    return {
      updated: {
        hour: '',
        minutes: ''
      }
    }
  },

  props: ['source'],

  mounted: function () {
    moment.locale('pt')

    this.updated.hour = moment().format('HH')
    this.updated.minutes = moment().format('mm')
    this.updated.seconds = moment().format('ss')
  }
}
</script>

When callAPI() is reloaded, I would like to update time as well. I'm newbie with Vue.js (or this kind of framework) and I'm struggling how to handle this kind of dynamic information.

Thanks in advance.

Upvotes: 0

Views: 1645

Answers (2)

Bert
Bert

Reputation: 82439

There are a couple of ways you could do this.

If the source property of your parent component is updated by callAPI then this would be as simple as moving your code into the updated handler.

export default {
  data: function () {
    return {
      updated: {
        hour: '',
        minutes: ''
      }
    }
  },

  props: ['source'],
  methods: {
    update(){
      moment.locale('pt')

      this.updated.hour = moment().format('HH')
      this.updated.minutes = moment().format('mm')
      this.updated.seconds = moment().format('ss')

    }    
  },
  updated: function () {
    this.update()
  },
  mounted: function(){
    this.update()
  }
}

Since it's not clear that you are updating any properties of the sourceupd, another way would be to just call the method using a ref.

In the Parent component template:

<sourceupd ref="sourceupd" class="source" v-bind:source='source'></sourceupd>

In your mounted handler:

setInterval(() => {
  callAPI()
  this.$refs.sourceupd.update()
}, 1024 * 3)

And change sourceupd:

export default {
  data: function () {
    return {
      updated: {
        hour: '',
        minutes: ''
      }
    }
  },

  props: ['source'],

  methods: {
    update(){
      moment.locale('pt')

      this.updated.hour = moment().format('HH')
      this.updated.minutes = moment().format('mm')
      this.updated.seconds = moment().format('ss')

    }    
  },

  mounted: function () {
    this.update()
  }  
}

I should also point out that you should add seconds to the updated property of your data, otherwise it will not be reactive.

  updated: {
    hour: '',
    minutes: '',
    seconds: ''
  }

Upvotes: 1

Bill Criswell
Bill Criswell

Reputation: 32921

I'd personally pass updated as property to the child. That way, whenever the parent updates, so will the child.

I also wouldn't have it as an object, but a timestamp instead so you can do whatever you want with it more easily.

Also, I'd use filters for formatting the hours minutes and seconds.

My Child component would look something like:

const Child = {
  props: {
    updated: Number,
  },

  filters: {
    format (timestamp, format) {
      return moment(timestamp).format(format || 'dddd, MMMM Do YYYY, h:mm:ss a')
    },
  },

  template: `
    <div class="child">{{ updated | format('ss') }}</div>
  `,
}

Then, as you update the parent's updated property it'll flow down into the child component.

Upvotes: 1

Related Questions