4
\$\begingroup\$

I'm in a project that's currently using vue. I'm at the moment developing validations for the inputs and in a way to make them more flexible, my idea was to create an intermediate component "Group Component" where I set as a property the input I want to load. As such, validations are imported in the component.

I've found difficulty understanding when the several inputs had passed the validations without errors in the "Page component", and to that problem I've figured out a solution, which I don't know if it's the ideal approach, since I'm using $ref to obtain the validations of the child components and on submission it validateds if all have passed.

the package I'm using for validations is vuelidate.

Is there a better approach?

Validation in submitting the form on "Page component"

 onSubmit() {
    setTimeout(() => {
       if (this.checkIfAllInputsFilled()) {
           console.log('yes');

       } else {
           console.log('no');

       }
     , 300)
 },
 checkIfAllInputsFilled() {
     let validationsObj = { email: this.$refs.email.$v.$invalid, password: this.$refs.password.$v.$invalid };
      return Object.keys(validationsObj).every((k) => !validationsObj[k]);
 }

All Files - code

Page component

<template>
    <div class="login">
        <form class="login__form" @submit.prevent="onSubmit" novalidate>
            <base-input-group
                component="Input"
                labelClass="authentication"
                :labelValue="$t('global.email')"
                inputId="email"
                inputType="email"
                inputName="email"
                inputClass="input--default input--authentication"
                inputValue=""
                :contentErrors="[
                    { key: 'required', message: $t('errors.gerals.required') },
                    { key: 'email', message: $t('errors.gerals.invalid') }
                ]"
                @get-value="form.email = $event"
                ref="email"
            />
            <div class="authentication__form__buttons display--flex">
                <base-button
                    type="submit"
                    classAttribute="button--default button--background button--authentication"
                    :text="$t('authentication.login')"
                />
            </div>
        </form>
    </div>
</template>
<script>
    // components
    const baseInputGroup = () => import( /* webpackChunkName: 'inputGroup' */  '../../../components/inputs/baseInputGroup');
    const baseButton = () => import( /* webpackChunkName: 'baseButton' */  '../../../components/buttons/baseButton');


    export default {
        components: {
            baseInputGroup: baseInputGroup,
            baseButton: baseButton
        },
        data() {
            return {
                active: false,
                form: {
                    email: ''
                }
            }
        },
        methods: {
            onSubmit() {
                setTimeout(() => {
                    if (this.checkIfAllInputsFilled()) {
                        console.log('yes');

                    } else {
                        console.log('no');

                    }
                }, 300)
            },
            checkIfAllInputsFilled() {
                let validationsObj = { email: this.$refs.email.$v.$invalid };
                return Object.keys(validationsObj).every((k) => !validationsObj[k]);
            }
        }
    }
</script>

Group component

<template>
    <div class="field-group" :class="{'field--errors': $v.value.$error, 'field--success': !$v.value.$error}">
        <label for="inputId" :class="`label label--${labelClass}`"> {{ labelValue }}</label>
        <component
            :is="componentInput"
            :inputId="inputId"
            :inputType="inputType"
            :inputName="inputName"
            :inputClass="inputClass"
            :value="inputValue"
            :valid="$v.value"
            @input-value="value = $event"
        />
         <component
            v-if="$v.value.$error"
            :is="componentErrors"
            :errorMessage="errorMessage"
        />

    </div>
</template>
<script>
    export default {
        props: {
            component: String,
            labelClass: String,
            labelValue: String,
            inputId: String,
            inputType: String,
            inputName: String,
            inputClass: String,
            inputValue: String,
            contentErrors: Array
        },
        data () {
            return {
                componentInput: null,
                componentErrors: null,
                value: '',
                validator: {},
                errorMessage: ''
            }
        },
        created() {
                import(`../../../validations/${this.inputName}.js`).then( validator =>  {
                    this.validator = validator.default;
                });

            this.loaderComponent()
                .then(() => { this.componentInput = () => this.loaderComponent(); })
        },
        methods: {
            fillMessageError() {
                 this.contentErrors.map( error => {
                    if (!this.$v.value[error.key]) this.errorMessage = error.message;
                });
            }
        },
        computed: {
            loaderComponent () {
                return () => import( /* webpackChunkName: 'input' */  `./childrens/base${this.component}`);
            },
            loaderComponentErrors () {
                return () => import( /* webpackChunkName: 'errors' */  './../errors/baseError');
            }
        },
        validations () {
            return {
                value : {
                    ...this.validator
                }
            }
        },
        watch: {
            '$v.value.$error': {
                deep: true, // so it detects changes to properties only
                handler(newVal, oldVal) {
                    if (newVal) {
                        if (!this.componentErrors) {
                            this.loaderComponentErrors()
                                .then((component) => { this.componentErrors = () => this.loaderComponentErrors(); });
                        }

                        this.fillMessageError();
                    } else {
                        this.$emit('get-value', this.value)
                    }
                }
            }
        }
    }
</script>

Input component

<template>
    <input
        :id="inputId"
        :type="inputType"
        :name="inputName"
        :class="inputClass"
        :value="inputValue"
        @blur="action"
        @keyup.enter="action"
    >
</template>
<script>
    export default {
        props: {
            inputId: String,
            inputType: String,
            inputName: String,
            inputClass: String,
            inputValue: String,
            valid: Object,
        },
        methods: {
            action($event) {
                this.$emit('input-value', $event.target.value);
                this.valid.$touch();
            }
        }
    }

</script>

```
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.