7

I receive from a WebAPI a JSON object that has this property:

"BirthDate": "2018-02-14T15:24:17.8177428-03:00",

the HTML:

<input type="date" v-model="BirthDate" />

I bind that object using VueJS, but VueJS give this message in the console:

The specified value "2018-02-14T15:24:17.8177428-03:00" does not conform to the required format, "yyyy-MM-dd".

On this case the only relevant part is 2018-02-14, I can discard the other information.

I tried to create a Two Way filter to convert that Date Time to the required format but did not have success. See VueJS two way filter

How can I convert and bind that Date/Time format to the required Date Format of the HTML date input ?

Tony
  • 16,527
  • 15
  • 80
  • 134

3 Answers3

13

Considering myDate is your property, you can use:

<input type="date" :value="myDate && myDate.toISOString().split('T')[0]"
                   @input="myDate = $event.target.valueAsDate">

Since v-model is only syntactic sugar to :value and @input, you can use them instead. In this case, we used and changed them a little (to format the String that is the output of the date input to a Date object and vice-versa).

Check demo and caveats below.

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!',
    myDate: new Date('2011-04-11T10:20:30Z')
  },
  methods: {
    setMyDateToToday() {
        this.myDate = new Date();
    },
    addADayToMyDate() {
      if (this.myDate) // as myDate can be null
        // you have to set the this.myDate again, so vue can detect it changed
        // this is not a caveat of this specific solution, but of any binding of dates
        this.myDate = new Date(this.myDate.setDate(this.myDate.getDate() + 1));
    },
  }
});
// Notes:
// We use `myDate && myDate.toISOString().split('T')[0]` instead
// of just `myDate.toISOString().split('T')[0]` because `myDate` can be null.

// the date to string conversion myDate.toISOString().split('T')[0] may
// have timezone caveats. See: https://stackoverflow.com/a/29774197/1850609
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <p>{{ message }}</p>

  <input type="date" :value="myDate && myDate.toISOString().split('T')[0]"
                     @input="myDate = $event.target.valueAsDate">

  <p>
  <code>
  myDate: {{ myDate }}</code>
  </p>

  <button @click="setMyDateToToday">Set date one to today</button>
  <button @click="addADayToMyDate">Add a day to my date</button>
</div>
tony19
  • 125,647
  • 18
  • 229
  • 307
acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • 1
    Blog post related: https://acdcjunior.github.io/how-bind-date-object-to-input-date-vue.js-v-model.html – aloisdg Dec 23 '19 at 09:08
  • If you want it in Local Date, Remove the Z new Date($event.target.valueAsDate.toISOString().replace('Z','') – user666197 Nov 18 '22 at 03:40
4

i think this not related to vueJs , the input type="date" expected a date in YYYY-MM-DD format, or empty see here : https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date,

it would be better if you split date object as date and time field

Taha Azzabi
  • 2,392
  • 22
  • 31
  • Yes, I need a way to convert that date to the required format, and bring it back, so I tought about using a Two Way filter in VueJS. – Tony Feb 14 '18 at 18:56
  • How to Split the date on the cliente, and when user changes it, put it back on the original format? – Tony Feb 14 '18 at 18:57
  • @tony use should computed property with getter and setter as a proxy for the date. As for the the formatting itself there's hundreds of ways to accomplish you can find online . – oniondomes Feb 14 '18 at 19:01
  • as @oniondomes said you should use computed property,i'll try to post an example on jsfiddle later – Taha Azzabi Feb 14 '18 at 19:09
  • @tony you should also keep in mind that `` won't work for the time you have in your raw data. – oniondomes Feb 14 '18 at 19:36
1

Correction to @acdcjunior in that this shouldn't be off by one day

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!',
    myDate: new Date('2011-04-11T10:20:30Z')
  },
  methods: {
    setMyDateToToday() {
        this.myDate = new Date();
    },
    addADayToMyDate() {
      if (this.myDate) // as myDate can be null
        // you have to set the this.myDate again, so vue can detect it changed
        // this is not a caveat of this specific solution, but of any binding of dates
        this.myDate = new Date(this.myDate.setDate(this.myDate.getDate() + 1));
    },
    getDateClean(currDate) {
        // need to convert to UTC to get working input filter
        console.log(currDate);
        let month = currDate.getUTCMonth() + 1;
        if (month < 10) month = "0" + month;
        let day = currDate.getUTCDate();
        if (day < 10) day = "0" + day;
        const dateStr =
            currDate.getUTCFullYear() + "-" + month + "-" + day + "T00:00:00";
        console.log(dateStr);
        const d = new Date(dateStr);
        console.log(d);
        return d;
    }
  }
});
// Notes:
// We use `myDate && myDate.toISOString().split('T')[0]` instead
// of just `myDate.toISOString().split('T')[0]` because `myDate` can be null.

// the date to string conversion myDate.toISOString().split('T')[0] may
// have timezone caveats. See: https://stackoverflow.com/a/29774197/1850609
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <p>{{ message }}</p>

  <input type="date" :value="myDate && myDate.toISOString().split('T')[0]"
                     @input="myDate = getDateClean($event.target.valueAsDate)">

  <p>
  <code>
  myDate: {{ myDate }}</code>
  </p>

  <button @click="setMyDateToToday">Set date one to today</button>
  <button @click="addADayToMyDate">Add a day to my date</button>
</div>
lastlink
  • 1,505
  • 2
  • 19
  • 29