javascriptphplaravelvue.jsvuejs2

Vue JS - Live running time elapsed from a date


Currently I have a time elapsed displayed on my blade file. However to see the updated time, I need to refresh everytime. I would like to display a dynamic time lapsed. Is there a way to do it?

My current code is just that I pass a created_date (defined from controller) to the script. From there, I will get the hours, minutes and seconds. (Might do days later). They I return it back to my blade file.

This is a part from my blade file:

<table class="table table-bordered small">
  <thead>
      <tr>
          <th width="2%">No</th>
          <th width="5%">
              Created At
          </th>
      </tr>
  </thead>
  <tbody>
      <tr v-for="(index,row) in records.data" :class="{'NPI_row_color':NPI_Order(row)}">
          <td>@{{index+1}}</td>
          <td>
              @{{ setTimer(row.created_at) }} 
          </td>
      <tr>
  </tbody>
</table>

And this is the vue js script:

<script type="text/javascript">
  $(function () {
      var vm = new Vue({
          el: '#shopify_marketplace',
          data: {
            //some of data here
          },
          methods: {
            //some other methods here
            onReload: function(){
              //few codes here and there
            },
            setTimer: function(created_at){

                const startDate = new Date(created_at);
                const now = new Date();
                const elapsedSeconds = Math.floor((now - startDate) / 1000);
                
                const day = Math.floor((elapsedSeconds / 3600));
                const hours = Math.floor(elapsedSeconds / 3600);
                const minutes = Math.floor((elapsedSeconds % 3600) / 60);
                const seconds = elapsedSeconds % 60;

                return `${hours}h ${minutes}m ${seconds}s`;
                
            },
          },
          filters: {
              autoCaps: function(value){
                  if(value != null) {
                      return value.toLocaleUpperCase();    
                  }
              },
          },
          ready: function () {
              this.onReload();
          },
      });
  });
</script>

Image below is what my current display is. But yeah need to refresh everytime to see it update. May I know how can I make the time running and 'ticking?'. I tried to use this setInterval function from javascript but I failed miserably.

current_display


Solution

  • You should change the key to force re-render which will trigger the function, something like this :

    <table class="table table-bordered small">
      <thead>
          <tr>
              <th width="2%">No</th>
              <th width="5%">
                  Created At
              </th>
          </tr>
      </thead>
      <tbody>
          <tr v-for="(index,row) in records.data" :class="{'NPI_row_color':NPI_Order(row)}">
              <td>@{{index+1}}</td>
              <td :key="currentTime">
                  @{{ setTimer(row.created_at) }} 
              </td>
          <tr>
      </tbody>
    </table>
    
    <script type="text/javascript">
      $(function () {
          var vm = new Vue({
              el: '#shopify_marketplace',
              data: {
                  // some of data here
                  currentTime: 0 // Add this property to track the current time
              },
              methods: {
                  // some other methods here
                  onReload: function(){
                      // few codes here and there
                  },
                  setTimer: function(created_at){
                      const startDate = new Date(created_at);
                      const now = new Date(this.currentTime); // Use the reactive currentTime
                      const elapsedSeconds = Math.floor((now - startDate) / 1000);
                      
                      const hours = Math.floor(elapsedSeconds / 3600);
                      const minutes = Math.floor((elapsedSeconds % 3600) / 60);
                      const seconds = elapsedSeconds % 60;
    
                      return `${hours}h ${minutes}m ${seconds}s`;
                  },
                  startTimer() {
                      // Update the currentTime every second
                      setInterval(() => {
                          this.currentTime = new Date().getTime();
                      }, 1000);
                  }
              },
              mounted() {
                  this.onReload();
                  this.startTimer();
              },
          });
      });
    </script>
    

    You can read more about the key attribute here.