Skip to content

Instantly share code, notes, and snippets.

@sproogen
Last active July 30, 2021 02:40
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save sproogen/147d75db261505e8a558a7fd11a20551 to your computer and use it in GitHub Desktop.
Save sproogen/147d75db261505e8a558a7fd11a20551 to your computer and use it in GitHub Desktop.
Vee Validate - Child Component Example
import Vue from 'vue';
const bus = new Vue();
export default bus;
<template>
<div>
<input v-validate data-rules="required" :class="{'has-error': errors.has("textInput")}" id="textInput" name="textInput" type="text">
<span class="error" v-show="errors.has("textInput")">{{ errors.first("textInput") }}</span>
</div>
</template>
<script>
import { find, propEq } from 'ramda'
import bus from './bus'
export default {
mounted() {
//Listen on the bus for the parent component running validation
bus.$on('validate', this.onValidate)
//Watch for the changes to the childs error bag and pass back to the parent
this.$watch(() => this.errors.errors, (newValue, oldValue) => {
const newErrors = newValue.filter(error =>
find(propEq('field', error.field))(oldValue) === undefined
)
const oldErrors = oldValue.filter(error =>
find(propEq('field', error.field))(newValue) === undefined
)
bus.$emit('errors-changed', newErrors, oldErrors)
})
},
methods: {
onValidate() {
this.$validator.validateAll();
if (this.errors.any()) {
bus.$emit('errors-changed', this.errors.errors)
}
},
},
beforeDestroy() {
//When destroying the element remove the listeners on the bus.
//Useful for dynaically adding and removing child components
bus.$emit('errors-changed', [], this.errors.errors)
bus.$off('validate', this.onValidate)
},
}
</script>
<template>
<div>
<child-component></child-component>
<button :disabled="errors.any()" :click="submit()"></button>
</div>
</template>
<script>
import bus from './bus'
import ChildComponent from './ChildComponent'
export default {
mounted() {
//Emit that validation is required on the bus
this.$on('veeValidate', () => {
bus.$emit('validate');
})
//Listen on the bus for changers to the child components error bag and merge in/remove errors
bus.$on('errors-changed', (newErrors, oldErrors) => {
newErrors.forEach(error => {
if (!this.errors.has(error.field)) {
this.errors.add(error.field, error.msg)
}
})
if (oldErrors) {
oldErrors.forEach(error => {
this.errors.remove(error.field)
})
}
})
},
methods: {
submit() {
//On button pressed run validation
this.$validator.validateAll()
if (!this.errors.any()) {
//Do Sumbit
}
}
}
components: {
ChildComponent,
},
};
</script>
@cdarken
Copy link

cdarken commented Apr 4, 2017

@sproogen mate, the line here https://gist.github.com/sproogen/147d75db261505e8a558a7fd11a20551#file-parentcomponent-vue-L16 is a bit misleading because at https://gist.github.com/sproogen/147d75db261505e8a558a7fd11a20551#file-parentcomponent-vue-L36 you're using this.$validator. Can you update the gist to be a bit more clear, please ?

@kamihouse
Copy link

Is there any way to make the errors object global? Would make things easier.

@pimboden
Copy link

I can't get this working... validateAll() is a promise, so I don't really see how this should work

@lehni
Copy link

lehni commented May 4, 2017

@sproogen I believe I found a simpler way to address this situation, see logaretm/vee-validate#468 (comment)

At the moment, this requires a bit of hacking with the internals of vee-validate to remove the beforeCreate() and mounted() hooks, but maybe this pattern can find its way into the library...

@StMacLennan
Copy link

I tried for 6 hours to get this working with my app (as I have deeply nested components). Eventually, I just used this Advanced -
Inject
and had it solved in 3 minutes flat. If you can't get the above to work, try the injection route!

@lattam
Copy link

lattam commented Jul 5, 2017

@stephenmac that's perfect, thanks! One line in child component solves everything (I have a form with several sub-form components).

inject: ['$validator']

@renanpro03
Copy link

@lattam this not worked for me... any idea?

@DraughtGlobe
Copy link

Simply adding that single line @lattam talks about didn't work for me either. I also had to do Vue.use(VeeValidate, { inject: false }); and manually set the validator on the parent element with: $validates: true,

@woodyalan
Copy link

I add inject: ['$validator'] in child component but show a warning Injection "__ob__" not found

@imjeen
Copy link

imjeen commented Sep 7, 2017

vee-validate@2.0.0-rc.14:
this.errors.errors should be this.errors.items

@pymarco
Copy link

pymarco commented Sep 8, 2017

I get Injection "__ob__" not found too, the same as @woodyalan.

@dokicro
Copy link

dokicro commented Feb 23, 2018

@lattam this works perfectly!

@CouturierDeA
Copy link

You can use the instance of the parent validator in the child component (this.$validator = this.$parent.$validator in child component created hook) to validate all of the child components from the parent instance.

@awgv
Copy link

awgv commented Apr 20, 2018

If someone stumbles on this gist in the future, you can also use Vue’s provide/inject API to request the parent’s validator instance.

@garymcm
Copy link

garymcm commented Apr 28, 2018

Taking the multiple clues from the last 10 messages here, the way I got this to work was:

Parent Component:

...
provide () {
    return { parentValidator: this.$validator }
  },
...

Child Component:

...
inject: [ 'parentValidator' ],
...
 created () {
    this.$validator = this.parentValidator
  }
...

@mixn
Copy link

mixn commented Jun 20, 2018

@garymcm That worked perfectly — thank you! :)

@tkachev-o
Copy link

@garymcm thank you .

@forforeach
Copy link

As @Banandrew wrote, you can use inject API. The link was updated so here is an updated link -> https://baianat.github.io/vee-validate/concepts/injections.html#injecting-parent-validator

@jurifo
Copy link

jurifo commented Aug 1, 2018

@garymcm thanks

@helmsquared
Copy link

@garymcm this worked perfectly, many thanks!

@jb-reynaud
Copy link

@garymcm thank you!

@arunasSlenderis
Copy link

@garymcm Thx man, was struggling for hours with this

@cby016
Copy link

cby016 commented Jan 17, 2019

Thanks @garymcm. Your 7 lines of example code were much more helpful than the documentation at https://baianat.github.io/vee-validate/concepts/injections.html#injecting-parent-validator

@cwhsu1984
Copy link

Thanks @garymcm. Your 7 lines of example code were much more helpful than the documentation at https://baianat.github.io/vee-validate/concepts/injections.html#injecting-parent-validator

You're DM Right!
Thanks @garymcm

@vicgonvt
Copy link

@garymcm WOW... amazing

@gonzalomc
Copy link

@garymcm Thanks !!

@alexander-elgin
Copy link

@garymcm That works perfectly. Thank you

@adamorlowskipoland
Copy link

@garymcm thank you :)

@limsocheat
Copy link

created () {
this.$validator = this.parentValidator
}

It works, Thanks.

@Antonio-naddeo
Copy link

@garymcm thank you, it worked perfectly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment