Does Vuejs have the ability to combine data fields into one?

Viewed 26

I currently have a datetime field in my vue application. I want to split it up, but that would mean having to split it up in my database as well, which I am not interested in. I still want to keep the datetime column in my database table.

So my idea was to make it like 3 seperate fields: datetime, date and time. When a user has entered a date and time, these can be merged into the datetime field. In Python you would do something like: datetime.datetime.combine( date, time )

Is there are similar method in Vue, or is there a better way of getting around this?

    <b-form-row>
      <b-col lg="6">
        <b-form-group :label="$t('check in time')">
          <time-picker v-model="guest.checkInDateTime"  />
        </b-form-group>
      </b-col>
    </b-form-row>

    <b-form-row>
      <b-col lg="6">
        <b-form-group :label="$t('check in date')">
          <date-picker v-model="guest.checkInDateTime"  />
        </b-form-group>
      </b-col>
    </b-form-row>

    <b-form-row>
      <b-col lg="6">
        <b-form-group :label="$t('check in time and date')">
          <date-time-picker v-model="guest.checkInDateTime"
                            :format="format"
                            :show-second="false"
                            type="datetime"/>
        </b-form-group>
      </b-col>
    </b-form-row>
1 Answers

Working with dates in Javascript can be nuanced. In Javascript, assuming you have both a date value and a time value, you can easily combine these into a date string used by an html date picker like this:

const date = '2022-08-10' // string returned from date input
const time = '15:00:00' // string returned form time input
const checkInDateTime = date + 'T' + time // ISO String

If you're starting with a Date and you want to break it into a date value and a time value, it's almost easier using string manipulations than working with the Date obj, unless you're using a helper library like dayjs.

Examples:

// Assuming we have a date in ISO String format YYYY-MM-DDTHH:mm:ss
const dateFromString = dateValueFromDB.split('T')[0]
const timeFromString = dateValueFromDB.split('T')[1]


// using Date obj
const d = new Date(dateValueFromDB);
const dateFromObj = `${d.getFullYear()}-${('' + (d.getMonth() + 1)).padStart(2, '0')}-${('' + date.getDate()).padStart(2, '0')}`
const timeFromObj = `${d.getHours()}:${('' + d.getMinutes()).padStart(2,'0')}:${('' + d.getSeconds()).padStart(2,'0')}`

// using dayjs library
const dateFromDayjs = dayjs(dateValueFromDB).format('YYYY-MM-DD')
const timeFromDayjs = dayjs(dateValueFromDB).format('HH:mm:ss')

Now to answer your original question. Once we know how we're getting the correct values, in Vue.js, we can easily get and set these date values using a computed property and a custom setter.

<script>
export default {
  data() {
    return {
      guest: {
        checkInDateTime: '2022-09-10 15:00:00' // timestamp returned from database
      }
    }
  },
  computed: {
    time: {
      get() {
        return dayjs( this.guest.checkInDateTime ).format('HH:mm:ss')
      },
      set(val) {
        this.guest.checkInDateTime = this.date + 'T' + val
      }
    },
    date: {
      get() {
        return dayjs(this.guest.checkInDateTime).format('YYYY-MM-DD')
      },
      set(val) {
        this.guest.checkInDateTime = val + 'T' + this.time
      }
    }
  }
}
</script>

Here's the html:

<template>
  <div class="datetime-pickers">
    <p>date: <input type="date" v-model="date" /></p>
    <p>time: <input type="time" v-model="time" /></p>
    <p>checkInDateTime: <input type="datetime-local" v-model="guest.checkInDateTime" /></p>
  </div>
</template>

When any of the three values are set, the other two are updated accordingly. Here's a CodePen showing this in action:

https://codepen.io/ryanhightower/pen/ExLPobY?editors=1010

Related