Srdjan Milic
Srdjan Milic

Reputation: 367

Pause functions on page history forward backward

There is Home.vue and Statistics.vue pages. Home.vue render the TableFields.vue component. At Home.vue there are fields numbers with initial value "3" set on page load. Set interval on calculate function adds numbers every two seconds. How to achieve, that when going from '/' to '/statistics' all the changing should be paused, and on returning back it should be resumed? Bellow each field at home page, already there are buttons that toggle setInterval() function and stop/resume calculations. Basically, when going from "/" to "/statistics" clearInterval() should be triggered that stops the calculations at "/" page. @Saksham TableFields.vue:

<template>
  <div>
    <table class="table-a">
      <tr>
        <th>A</th>
        <td class="sign">{{ this.randomSign.A }}</td>
        <td>{{ initialValue.A }}</td>
        <td v-show="this.randomSign.A == '+'">&#x2B06;</td>
        <td v-show="this.randomSign.A == '-'">&#x2B07;</td>
      </tr>
    </table>
    <button @click="toggleIntervalA()">
      <span v-show="this.startStop.A">Stop</span>
      <span v-show="!this.startStop.A">Start</span>
    </button>
    <table class="table-b">
      <tr>
        <th>B</th>
        <td class="sign">{{ this.randomSign.B }}</td>
        <td>{{ initialValue.B }}</td>
        <td v-show="this.randomSign.B == '+'">&#x2B06;</td>
        <td v-show="this.randomSign.B == '-'">&#x2B07;</td>
      </tr>
    </table>
    <button @click="toggleIntervalB()">
      <span v-show="this.startStop.B">Stop</span>
      <span v-show="!this.startStop.B">Start</span>
    </button>
  </div>
</template>

<script>

export default {
  name: 'TableFields',
  props: {
    changesA: {
      type: Array,
      required: false
    },
    changesB: {
      type: Array,
      required: false
    }
  },
  data () {
    return {
      fields: ['A', 'B'],
      startStop: {
        A: true,
        B: true
      },
      initialValue: {
        A: 3,
        B: 3
      },
      randomNumbersArray: [],
      randomSign: {
        A: '+',
        B: '+'
      },
      signsArray: ['+', '-'],
      interval: {
        A: null,
        B: null
      },
      localChanges: {
        A: [],
        B: []
      },
      timer: undefined
    }
  },
  computed: {},
  methods: {
    firstObjects () {
      for (let i = 0; i < this.fields.length; i++) {
        const date = new Date()
        const obj = {}
        obj.field = this.fields[i]
        obj.value = Number((Math.random() * 1 + 1).toFixed(2))
        obj.time = date.toLocaleTimeString()
        this.changesA.push(obj[0])
        this.changesB.push(obj[1])
        this.$emit('update:changesA', this.localChanges.A)
        this.$emit('update:changesB', this.localChanges.B)
      }
    },
    replaceNumbersArray () { // replace random A, B numbers at time interval
      const n1 = Number((Math.random() * 1 + 1).toFixed(2)) // n1 = first number (A)
      const n2 = Number((Math.random() * 1 + 1).toFixed(2)) // n2 = second number (B)
      this.randomNumbersArray.splice(0, 2, n1, n2)
    },
    toggleIntervalA () {
      this.startStop.A = !this.startStop.A
      if (this.startStop.A) {
        this.interval.A = setInterval(this.calculationsA, 2000)
      } else {
        clearInterval(this.interval.A)
      }
    },
    toggleIntervalB () {
      this.startStop.B = !this.startStop.B
      if (this.startStop.B) {
        this.interval.B = setInterval(this.calculationsB, 2000)
      } else {
        clearInterval(this.interval.B)
      }
    },
    calculationsA () {
      this.randomSign.A = this.signsArray[
        Math.floor(Math.random() * this.signsArray.length)
      ]
      this.randomSign.A === '+'
        ? (this.initialValue.A += this.randomNumbersArray[0])
        : (this.initialValue.A -= this.randomNumbersArray[0])
      const date = new Date()
      const newChange = {}
      newChange.field = 'A'
      newChange.value = this.randomNumbersArray[0]
      newChange.time = date.toLocaleTimeString()
      this.changesA.push(newChange)
      this.$emit('update:changesA', this.localChanges.A)
    },
    calculationsB () {
      this.randomSign.B = this.signsArray[
        Math.floor(Math.random() * this.signsArray.length)
      ]
      this.randomSign.B === '+'
        ? (this.initialValue.B += this.randomNumbersArray[1])
        : (this.initialValue.B -= this.randomNumbersArray[1])
      const date = new Date()
      const newChange = {}
      newChange.field = 'B'
      newChange.value = this.randomNumbersArray[1]
      newChange.time = date.toLocaleTimeString()
      this.changesB.push(newChange)
      this.$emit('update:changesB', this.localChanges.B)
    }
  },
  mounted () {
    this.firstObjects()
    setInterval(this.replaceNumbersArray, 2000)
    this.initialValue.A = this.$root.initialValue.A || 3
    this.initialValue.B = this.$root.initialValue.B || 3
    this.timer = setInterval(_ => {
      this.interval.A = this.calculationsA
      this.interval.B = this.calculationsB
    }, 2000)
  },
  beforeDestroy () {
    clearInterval(this.timer)
    this.$root.initialValue.A = this.initialValue.A
    this.$root.initialValue.B = this.initialValue.B
  }
}
</script>

<style lang="scss" scoped>
.table-b {
  margin-top: 15px;
}
.sign {
  width: 12px;
  text-align: center;
}
button {
  border: 1px solid transparent;
  border-radius: 0;
  background-color: #42b983;
  color: #ffffff;
  margin-top: 7px;
  padding: 5px 10px;

  &:hover {
    opacity: 0.9;
    cursor: pointer;
  }
}
</style>

Project repo: link

Upvotes: 0

Views: 115

Answers (1)

Saksham
Saksham

Reputation: 9380

Try using the beforeDestroy() hook to push the counter to either the root component or to vuex store (if you are using one) and fetch the counter in the mounted() hook once you return to the route to resume from there.

and use in your component as

export default {
...
    beforeDestroy () {
        this.$root.counter = this.counter;
    },
    mounted () {
        this.counter = this.$root.counter || 0;
    }
...
}

I have created a sandbox at https://codesandbox.io/s/preserve-timer-state-2osi7 which preserves the state of timer when we move out of the route and starts the timer from where we left.

Comment Notes:

As per you comment, it seems that you are trying to set a property to an object which is undefined. Initially there is no property by the name initialValue in the root component and you are trying to access a property A inside it.

You need to first check if initialValue is defined and then try to check for A

this.initialValue.A = this.$root.initialValue && this.$root.initialValue.A ?  this.$root.initialValue.A : 3

Also make sure your data has initialValue as an empty object

initialValue: {}

Upvotes: 1

Related Questions