Vee-validate: How to validate the fields within the parent and the children component in the same time ?

Created on 2 Mar 2017  Â·  13Comments  Â·  Source: logaretm/vee-validate

Versions:

  • VueJs: 2.1.10
  • Vee-Validate: 2.0.0-beta.23

Description:

when validating all fields within the parent component and children component, I try to use the Event Bus way to validate and submit the form , and How to know the result is valid?

the parent component validate and submit:

bus.$emit('validate');
this.$validator.validateAll();
if (!this.errors.any()) {
          //Do Sumbit
}

the parent fields were valid and the children were invalid, but the this.errors.any() value is always false.
Finally, I find the validator is asynchronous, so I want to use the promise like that:

this.$validator.validateAll().then(success => {
                if (! success) {
                    // handle error
                    return;
                }
                alert('From Submitted!');
  });

but the bus.$emit('validate') is different from above

✨ enhancement

Most helpful comment

@Fahad032 Seems like a centralized error object could be a nice option to avoid such issues, so that all components share the same error object, but that would require more complex organizing.

All 13 comments

I don't think it is possible to validate all of them at the same time, due to some complexities and that some rules maybe asynchronous, so there is no way to validate them at the same time atm.

I am using the same approach for both parent and child validation( in my case only parent has the submit trigger and the child has the fields). at my parent handler function I have tried:

// i have changed the errorsBag to vErrors using config()

          EventHub.$emit('validate');

            if(this.vErrors.any()){

                swal("Error!", 'Form validation failed, please be sure to fulfill the form properly!', "error");
                return this.requesting = false;

            }

it works fine, but throws some console error, that doesn't effect the work flow by the way. the error says:

Uncaught (in promise) anonymous {msg: "[vee-validate]: Validation Failed"}msg: "[vee-validate]: Validation Failed"__proto__: Object

is there a way to remove those error. Thanks

@Fahad032 You need to catch the promise:

validateAll().then(() => {
  // success
}).catch(() => {
  // error
});

if i use

validateAll().then(()=>{ 

}).catch(() => {

});

it removes the console error, but..
it always pass, it doesn't care about the child validations, i have also checked the errorsBag in vue dev tool. it becomes empty. for this reason i have forced to trigger this validate event manually, thus the child validate themselves and fills the errorbag.

@logaretm I understood.

It's always asynchronous to validate them, event though they are in the children components.

Please close the issue.


@Fahad032 you can try to do like:

Promise.all([
 bus.$emit('validate'), // children validator
 this.$validator.validateAll(), // parent validator
]).then(()=>{
 // ok
}).catch((err)=>{
 // error
});

Maybe also:

bus.$emit('validate'), // children validator
// parent validator
this.$validator.validateAll().then(()=>{
 // ok
}).catch((err)=>{
 // error
});

even also:

bus.$emit('validate'); // children validator
this.$validator.validateAll(); // parent validator
setTimeout(()=>{
 if(this.errors.any()){
 // error
 return;
}
 // ok
}, 0);

[note: my previous code example works fine for me except it is generating some console error( these console error has no effect on the work flow)]

@imjeen , I have tried all of them, seems no luck so far. To face the issue,
Make you parent component error free,
Leave your child component fields as blank( so that required field can fill the errorBags).

now if you try

this.$validator.validateAll(); // parent validator

it will always pass and run the success block( doesn't care for the child validation), in-fact it clears the child errors from the error bag, since the parent has no error. but the errors(from child components ) are expected.

Thanks

@Fahad032 Seems like a centralized error object could be a nice option to avoid such issues, so that all components share the same error object, but that would require more complex organizing.

@Fahad032 you should add the children errors to the parent errors by yourself, like below:

bus.$on('errors-changed', (errors) => {
// the children errors
 errors.forEach(e => {
    this.errors.add(e.field, e.msg, e.rule, e.scope);
 });
});

you must trigger the children event: bus.$emit('validate') (like in my code) to validate children fileds

Recent commits have added the ability to inject the parent validator into the child component, meaning both now share the same errorbag and the same fields, also the same validator instance which should make tackling this easier, please refer to #468

@logaretm even after injection validateAll on the parent validator doesn't trigger the validation of the child.
cf https://github.com/logaretm/vee-validate/issues/468#issuecomment-305145942

The inject solution described here solve my issue #677

this happens because Vue edits the data Asynchronously, the new errors not passed yet.
this will work fine.

bus.$emit('validate');
this.$validator.validateAll();
this.$nextTick(() => {
    if (!this.errors.any()) {
        //Do Sumbit
    }
})

https://vuejs.org/v2/api/#Vue-nextTick

Example of child component validation (in case if inject $validator doesn't work for some reason)
Parent component

  <el-input name="password"
            v-validate="{ required: true, min: '6', max: '8' }"
            :placeholder="$t('validation.attributes.password')"
            v-model="password">
  </el-input>
  <span class="form__field-message">{{ v_errors.first('password') }}</span>
  <el-input name="email"
            v-validate="{ required: true, email: true }"
            placeholder="Email"
            v-model="email">
  </el-input>
  <span class="form__field-message">{{ v_errors.first('email') }}</span>

  <inputs v-bind:someData="someData" :validator="$validator"/>

  <el-button class="form__submit" @click="onSubmit()" type="success">
    submit
  </el-button>

   import inputs from './inputs.vue';

   export default {
     components: {
       inputs,
     },
     data() {
       return {
         email: '[email protected]',
         password: '123123',
         someData: {
           someValue: null
         }
       }
     },
     methods: {
       onSubmit() {
         this.$validator.validateAll().then((valid) => {
           alert(`form valid ${valid}`);
         })
       }
     }
   }

Child "inputs" component

 <div>
      <el-input name="someValue"
            :data-vv-scope="v_scope"
            :placeholder="$t('validation.attributes.someValue')"
            v-validate="{ decimal: 3, required: true }"
            v-model="someData.someValue">
       </el-input>
       <span>{{ v_errors.first(v_scope ? `${v_scope}.someValue` : 'someValue') }}</span>
  </div>


   export default {
    props: {
       v_scope: this.v_scope,
       validator: this.validator,
       someData: this.someData
     },
    created() {
        if (this.validator) {
          this.$validator = this.validator;
        }
     },
   }

Vee-validate config

    export default {
        errorBagName: 'v_errors', // change if property conflicts
        fieldsBagName: 'v_fields',
       delay: 0,
        locale: 'en',
        dictionary: null,
        strict: true,
        classes: false,
        classNames: {
            touched: 'touched', // the control has been blurred
            untouched: 'untouched', // the control hasn't been blurred
            valid: 'valid', // model is valid
            invalid: 'invalid', // model is invalid
            pristine: 'pristine', // control has not been interacted with
            dirty: 'dirty' // control has been interacted with
        },
        events: 'input|blur',
        inject: true,
        validity: false,
        aria: true,
        // i18n: null, // the vue-i18n plugin instance,
        i18nRootKey: 'validations' // the nested key under which the validation messages will be located
    };
Was this page helpful?
0 / 5 - 0 ratings

Related issues

triffer picture triffer  Â·  3Comments

MaxMilton picture MaxMilton  Â·  3Comments

7immer picture 7immer  Â·  3Comments

parweb picture parweb  Â·  3Comments

schel4ok picture schel4ok  Â·  3Comments