Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make computed Vue properties dependent on current time?

I have a collection of Events. These will render in lists according to their status - upcoming/live/previous. Thus the rendering is dependent on the current time. How can I make the computed properties to update/recompute as time goes by?

<template>
    <div>
        <h2>Upcoming events</h2>
        <p v-bind:key="event.name" v-for="event in upcomingEvents">{{ event.name }}</p>

        <h2>Live events</h2>
        <p v-bind:key="event.name" v-for="event in liveEvents">{{ event.name }}</p>

        <h2>Previous events</h2>
        <p v-bind:key="event.name" v-for="event in previousEvents">{{ event.name }}</p>
    </div>
</template>

<script>
    import Event from '../Event.js'

    export default {
        data() {
            return {
                events: []
            }
        },

        computed: {
            upcomingEvents() {
                return this.events.filter(event => event.isUpcoming())
            },

            liveEvents() {
                return this.events.filter(event => event.isLive())
            },

            previousEvents() {
                return this.events.filter(event => event.isPrevious())
            },
        },

        mounted() {
            // this.events are populated here 
        }
    }
</script>
like image 617
ajthinking Avatar asked Oct 16 '18 13:10

ajthinking


2 Answers

You can declare a time-dependent data variable and use setInterval() to update it:

data() {
    return {
        events: [],
        now: Date.now()
    }
},
created() {
    var self = this
    setInterval(function () {
         self.now = Date.now()
    }, 1000)
},
computed: {
    upcomingEvents() {
        return this.events.filter(event => event.isUpcoming(this.now))
    },
    liveEvents() {
        return this.events.filter(event => event.isLive(this.now))
    },
    previousEvents() {
        return this.events.filter(event => event.isPrevious(this.now))
    }
}

Note that you need to use now in computed properties to make them update.

like image 69
ittus Avatar answered Oct 01 '22 02:10

ittus


One possibility for your case is $forceUpdate(). However, it should be note that it will work specifically for your case because you're NOT using child components.

If you were to use child components, you would then need to use slots within the parent component and insert the children within their respective slots.

So, for example, you could do:

created() {
    setInterval(() => {
        this.$forceUpdate()
    }, 5000)
}

Which will cause the entire component to re-render. This may or may not be the desirable interaction you're looking for.

like image 39
Ohgodwhy Avatar answered Oct 01 '22 01:10

Ohgodwhy