I'm having problems doing a form validation. I have a start date and an end date. I need to confirm that the end date is greater than the start date. I'm using vuejs and vuelidate. I'm working with an Input.vue component, which has a standard input being reused in other forms. I also have a Form.vue component that has Input.vue inside. And this Form.vue component is called both in the modal of creating a new event and in the editing mode. My problem is in the validation of when the event is edited. If you select an end date less than the start date, it doesn't allow saving the information, that's ok. However, when trying to correct it by selecting a date greater than the start date, and clicking on save again, it seems that it is no longer calling validation. With this, the error that the end date must be greater than the initial one does not disappear. I did several tests and noticed that validation is not called after the error occurs when editing. I do not know why.
component 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>
component 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>
component 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) {
....
}
},
validation
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;
Solved my issue with Vue.set. I realized that I was trying to detect the change of a property that I added later myself. So I had to use Vue.set when adding the property, so I could detect the change later, and then correctly validate the form. Thanks to whoever tried to help me!