Optimal method to refresh v-for when updating route in Vue.js seamlessly without having to manually reload the page

What is the best approach to re-render a v-for loop in my Vue.js application when switching to another route?

In my scenario, I am using Vuex, vuex-persistedstate, and moment for saving data in localStorage and displaying timestamps like "a moment ago".

However, how can I trigger a re-render of the v-for loop without changing the data from my API or manually reloading the page?

If you look at the screenshot below:

The Recent Activity data is always cached in localStorage. But if there are no new updates from the API, how can I ensure that the timestamps continue to update (e.g., "3 minutes ago", "4 minutes ago") without having to refresh the page manually?

This currently only happens upon page reload because of my code structure:

<template>
<div class="widget">
    <h4 class="widget-title">Recent Activity</h4>
    <ul class="activitiez">
        <li v-for="act in recentActivity" :key="act._id" :id="act._id">
            <div class="activity-meta">
                <i v-html="convertToMoment(act.created_at)"></i>
                <span v-html="act.activity"></span>
                <h6>by <a href="#" v-html="act.sent_name"></a></h6>
            </div>
        </li>
    </ul>
</div>
</template>

<script>
import {mapGetters, mapActions} from "vuex"

export default {
    created() {
        this.fetchRecentActivityData()
    },
    computed: {
        ...mapGetters(["recentActivity"])
    },
    methods: {
        ...mapActions(["fetchRecentActivityData"]),
        convertToMoment(data) {
            return moment(data).fromNow()
        }
    },
}
</script>

<style>

</style>

And here is my Vuex store code:

import axios from 'axios';

const state = {
    recentActivityStore: [],
    errorBag: null,
    timingStore: Date.now()
};

const getters = {
    recentActivity: state => state.recentActivityStore,
    recentActivityTiming: state => state.timingStore
};

const actions = {
    async fetchRecentActivityData({ commit }) {
        const recentAct = this.state.recentactivity.recentActivityStore
        if(_.isEmpty(recentAct)) {
            const response = await axios.get('/recent/activity')
            commit('UPDATE_RECENT_ACTIVITY', response.data)
        }
        commit('UPDATE_TIMING', Date.now())
    }
};

const mutations = {
    UPDATE_RECENT_ACTIVITY: (state, data) => {
        state.recentActivityStore = data
    },
    UPDATE_TIMING: (state, data) => {
        state.timingStore = data
    }
};

export default {
    state,
    getters,
    actions,
    mutations
};

How can I achieve auto-refreshing of my v-for loop without manual page refresh so that the timestamps keep updating? Any help would be greatly appreciated.

Thank you!

Answer №1

Here is a link to the Codepen example: https://codepen.io/anon/pen/qvgxRJ

To tackle this issue, you can create a Vue filter. Here's the code snippet for the filter: Vuejs time ago filter


filters: {
  timeago: function (pdate, ctime) {
     if (!pdate || !ctime) return ''
     return moment(pdate).from(ctime)
   }
 },
 

Once you have created the filter, you need to apply it in your HTML like this:

<i>{{act.created_at | timeago(currenttime)}}</i>

This calculates the time ago based on the current time. To keep updating the component every 50 seconds, update the current time value in setInterval:


data:()=>({
 currenttime: Date.now(),
 timer: ''
 }),
created() {
    this.fetchRecentActivityData()
    this.timer = setInterval(() => {this.currenttime = Date.now()}, 50000);
}

Here is the final code snippet that incorporates all these functionalities:


export default {
 data:()=>({
 currenttime: Date.now(),
 timer: ''
 }),
 filters: {
  timeago: function (pdate, ctime) {
     if (!pdate || !ctime) return ''
     return moment(pdate).from(ctime)
   }
 },
 created() {
    this.fetchRecentActivityData()
    this.timer = setInterval(() => {this.currenttime = Date.now()}, 50000);
 },
 beforeDestroy() {
    clearInterval(this.timer)
 },
 computed: {
    ...mapGetters(["recentActivity"])
 },
 methods: {
    ...mapActions(["fetchRecentActivityData"]),
 },
}

And in your HTML template, you can use the filter like this:


<li v-for="act in recentActivity" :key="act._id" :id="act._id">
    <div class="activity-meta">
        <i>{{act.created_at | timeago(currenttime)}}</i>
        <span v-html="act.activity"></span>
        <h6>by <a href="#" v-html="act.sent_name"></a></h6>
    </div>
</li>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering a Mongoose issue while attempting to load model files from a separate Mean.js project using the require function

I am currently working on a Mean.js project and in the process of familiarizing myself with this environment. To conduct some experiments, I created a parallel project for testing purposes in a separate folder where I am not using the Mean.js framework but ...

Issues with retrieving a result object from a MySQL query in NodeJS

I've been working on creating a logging system in NodeJS with a MySQL database. To establish the connection, I use the following code: const con = mysql.createConnection({ host : 'localhost', user : 'dbuser', passwor ...

What is the best way to retrieve the responseText using the jQuery.getJSON method within JavaScript?

I am currently facing an issue where I am attempting to retrieve information from a JSON file located in my directory by utilizing the jQuery.getJSON method. Unfortunately, when I try to access the object shown in the image, I am unable to extract the resp ...

Break down the text of a paragraph into separate words, placing each word within its own span element, and then add animations

I am facing an issue with my paragraph element that has the display property set to hidden. I have split each word of the paragraph and placed them inside individual span elements. My goal is to create an effect where each word comes from different locatio ...

How should an object be properly passed as a prop using vue router?

In my application, I have a PreviewProduct component that emits a product object to the App.vue file when clicked. My next goal is to pass this product object to the DetailedProduct component using the following method: handleProductClicked(product) { ...

When the input value is changed programmatically, the onchange event does not execute as expected

Having trouble updating the content of my dataTable when using JS script to change the quantity value. Here is a snippet from my code. <h:inputText id="counterFeatures" value="#{myBean.quantity}"> <f:ajax event="change" render="myDataTable" ...

Ways to Press the Enter Key on Different Browsers

Looking for a solution to get the keypress action working properly? I have a chat feature where I need to send messages. Here is what I have in the Form-tag (JSP based): function SendMessage() { if (event.keyCode===13) { ale ...

Find the nearest element with a specific class using jQuery

I am currently using jQuery version 1.12.4 for the purpose of retrieving the value from the closest element with a specific class selector. Unfortunately, I am encountering difficulty in selecting the closest element as desired. $(function() { $("[cla ...

Loading SVGs on the fly with Vue3 and Vite

Currently, I am in the process of transitioning my Vue2/Webpack application to Vue3/Vite. Here's an example of what works in Vue2/Webpack: <div v-html="require('!!html-loader!../../assets/icons/' + this.icon + '.svg')" ...

What sets axios apart from vue-axios?

I would love to learn more about the distinctions between axios and vue-axios. Which one is recommended for use, or do we need to utilize both when using an API? Appreciate any insights! ...

Showing a Bootstrap.vue b-table containing nested arrays within arrays

I am facing an issue while trying to display data in a b-table. Normally, it works well with most data sets. However, when I encounter another array nested within the referenced array, the rendering is not done properly. While working on this problem, I ...

Invoke JavaScript when the close button 'X' on the JQuery popup is clicked

I am implementing a Jquery pop up in my code: <script type="text/javascript"> function showAccessDialog() { var modal_dialog = $("#modal_dialog"); modal_dialog.dialog ( { title: "Access Lev ...

Determine the length of the string using an angular design

I have an input field and a span set up like this: <input type="password" name="account_password" placeholder="Enter your new password" autocomplete="off" ng-model="res.account.new_password" required="" ng-minlength="res.minlength" class="form-control" ...

What is the best way to display a PDF in a web browser using a JavaScript byte array?

I have a controller that sends the response Entity as a byte array in PDF form to an ajax call. However, I am struggling to display it in the browser despite trying various suggestions from old Stack Overflow questions. Here is the response from the Sprin ...

Parameterized Azure Cosmos DB Stored Procedure

I am currently learning about Azure Cosmos Db, and I am in the process of developing a simple JavaScript stored procedure that will return a document if a specific Id is provided. However, when I run the stored procedure, I do not receive a "no docs foun ...

Different ways to modify the color of a chart using am4chart

I am using am4chart to create a line chart on my website. The background of the website is black, so I need to make the chart white. I have tried changing the chart fill when creating the chart, but it didn't work at all. However, changing the chart ...

Retrieving the text of a selected option by its value

I need to create a menu that returns text based on a given value. For example, if the value is 0, I want it to return “zero”, and if it's 1, then “one”, and so on. I don't need to know which option is selected or auto-select anything, I j ...

Troubleshooting error in Vue project: "hasOwnProperty" property or method not supported by object in IE11

While working on a vue app with vue advanced webpack template, I didn't pay much attention to Internet Explorer compatibility. However, today when I tried running the app on IE browser, I encountered some strange errors. https://i.stack.imgur.com/1e6 ...

Tips on aligning three divs horizontally within a container while maintaining a height of 100%

UPDATE: The alignment has been corrected by adding floats. However, the height still doesn't fill 100%. Check out the new look: Image Link In my footer container, I want to arrange 3 columns (colored green, white, and red for clarity). Currently, the ...

What steps should I follow to include a message in the custom form validation rule in my React application?

I'm currently developing a chat application using React 18 and Firebase 9. For cleaner form validation, I have integrated the Simple Body Validator. Within the Register form, there's an input field of type file for uploading user avatars. The ...