结束日期必须小于开始日期,Vuelidate 和 VueJs

end date must be less than start date, Vuelidate and VueJs

我在进行表单验证时遇到问题。我有一个开始日期和一个结束日期。我需要确认结束日期大于开始日期。 我正在使用 vuejs 和 vuelidate。 我正在使用一个 Input.vue 组件,它有一个标准输入,可以在其他形式中重复使用。我还有一个 Form.vue 组件,里面有 Input.vue。这个 Form.vue 组件在创建新事件的模式和编辑模式中都会被调用。 我的问题在于验证事件何时被编辑。如果您 select 结束日期小于开始日期,则不允许保存信息,没关系。但是,当尝试通过 selecting 一个大于开始日期的日期来更正它并再次单击保存时,它似乎不再调用验证。这样,结束日期必须大于初始日期的错误就不会消失。我做了几次测试,发现在编辑时发生错误后不会调用验证。不知道为什么。

组件Input.vue:

 <template>
  <b-form-group :label="label" :label-for="labelFor">
    <b-form-input
      :id="labelFor"
      v-model="value"
      :type="type"
      :placeholder="placeholder"
      :class="{ 'is-invalid': this.isInvalid }"
      required>
    </b-form-input>
    <slot></slot>
  </b-form-group>
</template>

<script>
export default {
  name: 'InputForm',
  props: [ 'label', 'labelFor', 'vModel', 'type', 'placeholder', 'isInvalid' ],  
  computed: {
    value: {
      get() {
        return this.vModel
      },
      set(value) {
        this.newValue = value
        return this.$emit('emitValue', this.newValue)
      }
    }
  },
}
</script>

组件Form.vue:

<template>
  <b-form>
....
<InputForm
          class="col-8 pl-0"
          :label="'*Início'"
          :labelFor="'event_start_at_date'"
          :vModel="event.start_at_date"
          :type="'date'"
          @emitValue="($event) => event.start_at_date = $event"
        />
        <InputForm
          class="col-4 pr-0"
          v-if="!event.all_day"
          :labelFor="'event_start_at_time'"
          :vModel="event.start_at_time"
          :type="'text'"
          @emitValue="($event) => event.start_at_time = $event"
        />
      </b-col>
      <b-col cols="12" lg="6" class="d-flex align-items-end">        
        <InputForm
          class="col-8 pl-0"
          :label="'*Fim'"
          :labelFor="'event_end_at_date'"
          :type="'date'"
          :vModel="event.end_at_date"
          @emitValue="($event) => event.end_at_date = $event"
          :isInvalid="invalid.end_at_date.$error"
        >
          <b-form-invalid-feedback v-if="this.submitted" :state="invalid.end_at_date.$error == 0">Fim deve ser maior que início.</b-form-invalid-feedback>
        </InputForm>      
        <InputForm
          class="col-4 pr-0"
          v-if="!event.all_day"
          :labelFor="'event_end_at_time'"
          :vModel="event.end_at_time"
          :type="'text'"
          :isInvalid="invalid.end_at_date.$error"
          :class="{ 'error' : invalid.end_at_date.$error  }"
          @emitValue="($event) => event.end_at_time = $event"
        />
...
 </b-form>
</template>

export default {
  name: 'Form',
  props: [ 'event', 'event_shared', 'error', 'submitted' ],
  components: { Input },
computed: {
    invalid() {
      if(this.error.edit_event != undefined) {
        return this.error.edit_event
      } else if(this.error.event != undefined) {
        return this.error.event
      } else {        
        return false;
      }
    },
    stateInvalid() {
      if(this.error.edit_event != undefined) {
        return this.error.edit_event
      } else if(this.error.event != undefined) {
        return this.error.event
      } else {        
        return 0;
      }
    },
  },
watch: {
    event() {
      let newEvent = this.event
      this.$emit('emitObj', newEvent)
    },
  },
}
</script>

组件ModalEditEvent.vue:

    ...
<VWarningErrorForm v-if="$v.$error" />
            
            <FormEvent
              :event="edit_event"
              :event_shared="get_shared_users_id"
              :error="this.$v"
              :submitted="this.submitted"
              @emitObj="($event) => edit_event = $event"
            />
...
<b-button 
          v-if="editEvent && !view_popover_save"
          variant="primary" type="submit" @click="save()">Gravar</b-button>
...
<script>
import moment from 'moment';
import { required } from "vuelidate/lib/validators";
import isAfterDate from '@/functions/isAfterDate'
...
validations: {
    edit_event: {
      name: {
        required
      },
      end_at_date: {
        required: function(value) {
          return isAfterDate(value, this.edit_event);
        }
      },
    },
  },
...
save() {
      this.submitted = true;
      this.$v.$touch();
      if(!this.$v.$error) {
....
      }      
    },

验证

import moment from 'moment';

function isAfterDate(value, vm) {
  let hour =  function(att) {    
    return `${att[0]}${att[1]}`;
  }
  let minute = function(att) {
    return `${att[3]}${att[4]}`;
  }
  
  let start = moment(vm.start_at_date).set({hour: hour(vm.start_at_time), minute: minute(vm.start_at_time) })._d
  let end = moment(vm.end_at_date).set({hour: hour(vm.end_at_time), minute: minute(vm.end_at_time) })._d

  return end >= start;
}

export default isAfterDate;

Vue.set 解决了我的问题。我意识到我正在尝试检测我后来自己添加的 属性 的变化。所以我必须在添加 属性 时使用 Vue.set,这样我可以稍后检测到更改,然后正确验证表单。感谢所有试图帮助我的人!