Sajax
Sajax

Reputation: 93

Methods of formatting a Vuex object value

I'm trying to understand how to use values in a Vuex store and do some formatting, critically I'm trying to figure out the Vue way of formatting a timestamp contained within an object in the store and while iterating over the object.

For example using the following store

 const state = {
   events: {
     0: {
       id: 0,
       name: 'Example Event',
       start: 14907747374,
       end: 14907747674,
       entries: [0, 1]
     },
     1: {
       id: 1,
       name: 'Example Event 2',
       start: 14907740364,
       end: 14907740864,
       entries: [1]
     }
   },
   entries: {
     0: {
       id: 0,
       name: 'John Doe',
     },
     1: {
       id: 1,
       name: 'Paul Smith'
     }
   }
 }

I then have a getter to return all the events

export const events = state => state.events

And then I want to display the events as a list/table etc in component

<template>
  <div class="events">
    <template v-for="event in getAllEvents">
       <div class="event>
         {{ event.name }} || {{ event.start }}
       </div>
    </template>
  </div>
</template>

<script>
  export default {
    name: 'events',
    computed: {
      getAllEvents: function () {
        return this.$store.state.events
      }
    }
  }
</script>

So this would display

Example Event || 14907747374
Example Event 2 || 14907740864

whereas I need to display

Example Event || Jan 3rd 2017 14:15
Example Event 2 || Jan 3rd 2017 14:45

So within the v-for I want to format the 'event.start' timestamp into a human readable date and this where I'm not sure which method is the Vue way of doing it.

Filters

I've done similar before with Angular 1 filters, however my understanding of Vue Filters is they are specific to Components whereas they were available everywhere in Angular 1. Formatting the date seems like a common task that I should be able to write a single function and use it everywhere required. I could write the function in another module and import it into the the Component but I would still need to write the filter in each component where I wish to use it but at least the logic would be separate.

Component Method Function

Same issues as the filters here, logic can be separate function but I still have duplication of the filters themselves

Separate Component

Probably the best solution I've thought of but it feels like a misuse of Components for such minor function

<template>
  <span>{{ formattedDate }}</span>
</template>

<script>
  import 'moment'
  export default {
    name: 'humanDate',
    props: ['timestamp'],
    computed: {
      formattedDate: function () {
        return moment(timestamp).format()
      }
    }
  }
</script>

Then using the component as such

<human-date timestamp="event.start"></human-date>

Is there a better way that I'm missing and is creating components for small things such as this a reasonable use of components?

Upvotes: 2

Views: 2315

Answers (1)

PatrickSteele
PatrickSteele

Reputation: 14677

Look into Mixins. I created a quick-n-dirty mixin for formatting dates using moment.js:

import moment from 'moment'

export default {
    formatDateMixin: {
        methods: {
            formatDate: function(value) {
                if( !value) return '';
                
                return moment(value).format('YYYY-MM-DD HH:mm:ss');
            }
        }
    }
}

Plug it into your main Vue instance:

Vue.mixin(formatDateMixin);

And now you can use it in any template:

{{ event.name }} || {{ formatDate(event.start) }}

Upvotes: 5

Related Questions