Search code examples
vue.jsmomentjsvuejs3v-model

How can i pull dynamic data using v-model and moment js


I can already pull the data from api with v-model, but this is how i see the date 2022-04-23T13:39:00+03:00 but I want it to come this way 2022-04-23 13:39

Here is my html code

<Field
  class="form-control"
  type="text"
  v-model="date"
  name="date"
  :placeholder="$t('form.label.date')"
/>

Here is my ts code

  data() {
    date:"",
  }
  setup() {
    const dateFormat = (date) => {
      return moment(date).format("YYYY-MM-DD HH:mm");
    };
  }

Solution

  • If you are only rendering the value and don't need to setup two-way binding or reactivity, you can just resolve the formatting before passing the formatted value to the template.

    You can also pass a formatter function to the template that will render the formatting to you liking.

    While there are several options for formatting dates. To avoid adding additional dependencies, I'm using Intl.DateTimeFormat in the example. It's a little hacky, since the format is not in any international standard (or it is, and just don't know which one). I've also used date-fns with success, but as mentioned in the comments, you should not be using moment. Moment is built in a way that doesn't allow tree-shaking unused parts during packaging, so leads to bloat.

    const formatter = (dateStr) => {
      const date = new Date(dateStr)
      if (isNaN(date)) return "-- invalid date --";
    
      // fr-CA for YYYY-MM-DD + en-GB for 24hour hh:mm:ss
      return new Intl.DateTimeFormat('fr-CA', {
        year: 'numeric',
        month: 'numeric',
        day: 'numeric',
        timeZone: 'UTC'
      }).format(date) + " " + new Intl.DateTimeFormat('en-GB', {
        hour: 'numeric',
        minute: 'numeric',
        second: 'numeric',
        timeZone: 'UTC'
      }).format(date)
    }
    
    Vue.createApp({
      setup() {
        const date = Vue.ref("2022-04-23T13:39:00+03:00");
    
        // using ref
        const dateFormatted = formatter(date.value);
    
        return {
          date, // date string ref, to allow reactivity
          dateFormatted, // pass non-reactive value to display
          formatter // pass formatter function if reactive changes are needed
        }
      }
    }).mount("#app");
    input {
      width: 400px;
      padding: 6px;
      margin-top: 2px;
    }
    <script src="https://unpkg.com/[email protected]/dist/vue.global.prod.js"></script>
    <div id="app">
      <p>Date (v-model)<br/><input v-model="date" /></p>
      <p>Formatted with Intl (read-only)<br/> <input :value="dateFormatted" disabled/></p>
      <p>Reactive formatted with Intl (read-only)<br/> <input :value="formatter(date)" disabled /></p>
    </div>