Vee-validate: Pass errors to custom input components

Created on 28 Jan 2017  路  8Comments  路  Source: logaretm/vee-validate

Versions:

  • VueJs: 2.1.0
  • Vee-Validate: 2.0

Description:

In the documentation section 'Component Validation', one has to pass the errors as attributes to the custom input component:

<custom-input v-validate="'required|email'" data-vv-value-path="innerValue" data-vv-name="custom" label="Email" :has-error="errors.has('custom')"></custom-input>

This can get quite verbose if one wants to also have the error message.

Would it be reasonable to have the errors passed directly to the component ?

Steps To Reproduce:

Most helpful comment

I found a simple way around the problem. I simply pass the validation rules as a prop named 'validation'

FormText.vue

<template>
  <div class="form-group row" :class="{ 'has-danger' : errors.has(name) }">
    <label class="col-sm-3 col-form-label form-control-label" :for="name">{{ label }}</label>
    <div class="col-sm-9">
      <input type="text" :id="name" :name="name" v-bind:value="value" v-validate="validation" v-on:input="onInput" :placeholder="placeholder ? placeholder : name" :readonly="readonly">
      <div class="form-control-feedback" v-if="errors.has(name)">{{ errors.first(name) }}</div>
    </div>
  </div>
</template>

<script>
export default {
  props: ['label', 'value', 'name', 'placeholder', 'readonly', 'validation'],
  methods: {
    onInput (event) {
      this.$emit('input', event.target.value)
    }
  }
}
</script>

In the parent component:

//
<form-text label="Email" name="email" v-model="email" validation="'required|email'"></form-text>
//

This seems to do the trick

All 8 comments

data-vv-value-path attribute isn't needed actually, it is only needed if you want to have validateAll support for components. I could simplify it to specific attribute names but 3rd party components would still need dynamic specification.

I'm planning to get rid of the data-vv-value-path and replace it with a simpler syntax, probably I will increase the number of stuff you can pass to the directive.

EDIT: I took a look at your PR and it seems I misunderstood what you need to do, the plugin offers dealing with components as both inputs or as an independent entity. what you are suggesting can be done using events to keep things in sync which can be the user responsibility, take a look at: http://vee-validate.logaretm.com/examples#event-bus-example

ah ok, missed that one, but does it allow me to define the validation rules in the parent but let me show the errors on the child component ?

So for example, if i have an input component:

FormText.vue

<template>
  <div class="form-group row" :class="{ 'has-danger' : errors.has(name) }">
    <label class="col-sm-3 col-form-label form-control-label" :for="name">{{ label }}</label>
    <div class="col-sm-9">
      <input type="text" :id="name" :name="name" v-bind:value="value" v-on:input="onInput" :placeholder="placeholder ? placeholder : name" :readonly="readonly">
      <div class="form-control-feedback" v-if="errors.has(name)">{{ errors.first(name) }}</div>
    </div>
  </div>
</template>

<script>
export default {
  props: ['label', 'value', 'name', 'placeholder', 'readonly'],
  methods: {
    onInput (event) {
      this.$emit('input', event.target.value)
    }
  }
}
</script>

and in the parent element
Parent.vue

<template>
//
<form-text label="Email" name="email" v-model="email" v-validate="'required|email'">
//
</template>

Would i be able to have the errors show up in the FormText.vue template ?

Hope this makes sense

I found a simple way around the problem. I simply pass the validation rules as a prop named 'validation'

FormText.vue

<template>
  <div class="form-group row" :class="{ 'has-danger' : errors.has(name) }">
    <label class="col-sm-3 col-form-label form-control-label" :for="name">{{ label }}</label>
    <div class="col-sm-9">
      <input type="text" :id="name" :name="name" v-bind:value="value" v-validate="validation" v-on:input="onInput" :placeholder="placeholder ? placeholder : name" :readonly="readonly">
      <div class="form-control-feedback" v-if="errors.has(name)">{{ errors.first(name) }}</div>
    </div>
  </div>
</template>

<script>
export default {
  props: ['label', 'value', 'name', 'placeholder', 'readonly', 'validation'],
  methods: {
    onInput (event) {
      this.$emit('input', event.target.value)
    }
  }
}
</script>

In the parent component:

//
<form-text label="Email" name="email" v-model="email" validation="'required|email'"></form-text>
//

This seems to do the trick

Glad to hear, I guess I will close this issue now.

Due to the way Vue 2.x handles attributes, this no longer works by the way. The validation prop is not applied to v-validate in the child correctly. The better solution for anyone coming across this would be to inject the validator into the child.

@sebastianbarfurth I am trying this and not having any luck. I inject the validator, but I cannot see any errors when I do errors.first(inputName). inputName is also a prop I pass whic is a string, to match the v-model.

Do you have Vue dev tools? If so, check if the errors do appear on the component. For debugging purposes you could also try to hardcode the name of the input and see if that works.

this certainly isn't working

Was this page helpful?
0 / 5 - 0 ratings