I tried to create reusable components in my vue project. This is part of my training which I am going through. But I think I need a little help with my code which is confusing me.
let validations = {}
validations.firstName = function(e, that) {
if (e.target.value == "") that.errors = {
[that.labelID]: 'Please enter your first name'
}
else return true
that.input_error = !that.input_error
}
validations.phone = function(e, that) {
if (e.target.value == "") that.errors = {
[that.labelID]: 'Please enter phone number'
}
else if (e.target.value.length > 10) that.errors = {
[that.labelID]: 'Phone number should be 10 digits only'
}
else return true
that.input_error = !that.input_error
}
validations.email = function(e, that) {
if (e.target.value == "") that.errors = {
[that.labelID]: 'Please enter email'
}
else return true
that.input_error = !that.input_error
}
Vue.component('childInput', {
template: '#my-child-input',
data() {
return {
errors: {},
input_error: false
}
},
props: {
labelID: String,
label: String,
inputType: {
type: String,
default: 'text'
},
value: {
type: [String, Boolean, Number],
default: null
},
},
methods: {
handleInput(e) {
this.$emit("input", e.target.value)
},
handleFocusIn(e) {
this.errors = {[this.labelID]: ''}
if (this.input_error) this.input_error = !this.input_error
},
handleFocusOut(e) {
switch (this.labelID) {
case 'firstName':
case 'phone':
case 'email':
validations[this.labelID](e, this)
break;
default:
console.log('in default last name')
break;
}
}
}
});
new Vue({
el: '#app',
data() {
return {
event: {
firstName: '',
phone: '',
email: ''
}
};
},
methods: {
handleSubmit(e) {
// I can access firstName, phone and email.
// But how to access the validation functions written in child component
console.log('All data: ', this.event)
}
}
})
.someStyleClass {
margin-bottom: 20px;
}
.input_error {
border-color: red !important;
color: red;
}
.labelStyle {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<!-- Parent Component -->
<div id="app">
<div class="someStyleClass">
<child-input v-model="event.firstName" label="First Name" label-i-d="firstName" />
</div>
<div class="someStyleClass">
<child-input v-model="event.phone" label="Phone" label-i-d="phone" />
</div>
<div class="someStyleClass">
<child-input v-model="event.email" label="* Email" label-i-d="email" input-type="email" />
</div>
<button type="submit" v-on:click="handleSubmit">Validate & Submit</button>
</div>
<!-- Child Component -->
<template id="my-child-input">
<div>
<label class="labelStyle" :class="{input_error}">{{ label }}</label>
<input :class="{input_error}" :value="value" :type="[inputType]" v-on:input="handleInput" v-on:focusout="handleFocusOut" v-on:focusin="handleFocusIn"/>
<div v-if="errors[labelID]" :class="{input_error}">{{errors[labelID]}}</div>
</div>
</template>
I am able to validate input fields at child level and show its associated error near the input field upon focusout event. I can also access firstName, phone & email in my parent component. But when I submit the button from parent, I am unable to validate the fields. Since the validations are at child level and so are the errors.
How do I check for validations and make sure the firstName, phone & email are valid after I click the button.
Update
Each time when the users inputs wrong data in the input fields the data is being validated individually at the child level. But I don't see a way to find the same in my parent component. Because my parent component's data variables are being updated simultaneously on input.
How to validate at parent level after clicking on submit without ref's and without the use of additional libraries?
value, not raw target.value