Usage with other frameworks
Vuelidate-error-extractor is really flexible and can be used with pretty much any Vue UI framework or CSS framework.
Usage with ElementUI
ElementUI has its own validation scheme that uses AsyncValidator. You can however pass custom messages to its el-form-item
component.
To do that, you will have to add an el-form
wrapping component.
<el-form label-width="120px" size="mini">
<form-group :validator="$v.sizeForm.name">
<el-form-item
slot-scope="{ firstErrorMessage }"
:error='firstErrorMessage'
label="Activity name"
>
<el-input v-model="sizeForm.name"/>
</el-form-item>
</form-group>
</el-form>
This works, but is a bit too much boilerplate for my taste.
I would rather wrap the el-form-item
in an invisible component. That way we can skip 2 rows of boilerplate.
<template>
<el-form-item v-bind="$attrs" :label="label" :error='firstErrorMessage'>
<slot/>
</el-form-item>
</template>
<script>
import { singleErrorExtractorMixin } from "vuelidate-error-extractor";
export default {
name: "el-form-item-extended", // or what ever you want
extends: singleErrorExtractorMixin,
inheritAttrs: false
};
</script>
You can be more specific with the props that get assigned, but for simplicity this will do.
<el-form label-width="120px" size="mini">
<el-form-item-extended label="Activity name" :validator="$v.sizeForm.name">
<el-input v-model="sizeForm.name"/>
</el-form-item-extended>
</el-form>
Live ElementUI example
Usage with iView
iView uses the same mechanics and props as ElementUI.
Adapt the above example for it by using Form
and FormItem
components.
Usage with Framework7
This one is а bit simpler. We just need a simple invisible wrapper.
<template>
<div>
<slot :attrs="{ errorMessage: firstErrorMessage, errorMessageForce: hasErrors }" />
</div>
</template>
<script>
import { singleErrorExtractorMixin } from 'vuelidate-error-extractor'
export default {
name: 'form-group', // or what ever you want
extends: singleErrorExtractorMixin,
inheritAttrs: false,
}
</script>
Then we use it like so:
<form-group :validator="$v.name">
<f7-input
v-model="name"
slot-scope="{ attrs }"
v-bind="attrs"
type="text"
placeholder="Enter number"
/>
</form-group>
Usage with Vuetify
Vuetify's v-text-field
can be passed an errorMessages
prop that is an array of error messages.
We will pass our activeErrorMessages computed property to v-text-field
via a scoped slot.
<template>
<div>
<slot
:attrs="{ errorMessages: activeErrorMessages, success: isValid }"
:hasErrors="hasErrors"
/>
</div>
</template>
<script>
import { singleErrorExtractorMixin } from "vuelidate-error-extractor";
export default {
extends: singleErrorExtractorMixin
};
</script>
Now we can use it like so:
<form-group :validator="$v.form.email">
<v-text-field
slot-scope="{ attrs }"
v-bind="attrs"
v-model="form.email"
label="Email with wrapper"
@input="$v.form.email.$touch()"
/>
</form-group>
Live Vuetify example
Usage with MintUI
Mint-UI has only one field that supports validation state so its really easy to create a wrapper around it.
<template>
<mt-field :v-bind="$attrs" :state="state" v-model="model"><slot/></mt-field>
</template>
<script>
import { singleErrorExtractorMixin } from "vuelidate-error-extractor";
export default {
name: 'FormGroup',
extends: singleErrorExtractorMixin,
inheritAttrs: false,
props: {
value: {
type: [Number, String],
default: null
}
},
computed: {
model: {
get () {
return this.value
},
set (value) {
this.preferredValidator.$touch()
this.$emit('input', value)
}
},
state () {
return this.hasErrors ? 'error':
this.isValid ? 'success':
null
}
}
};
</script>
After we register the global component we can use it like so:
<form-group :validator="$v.form.name" v-model="form.name" label="Some label"/>
Live MintUI example
Usage with MuseUI
This is very similar to how ElementUI and iView work but you pass an error-text
prop.
<template>
<mu-form-item v-bind="$attrs" :error-text="firstErrorMessage" :label="label">
<slot/>
</mu-form-item>
</template>
<script>
import { singleErrorExtractorMixin } from "vuelidate-error-extractor";
export default {
extends: singleErrorExtractorMixin,
inheritAttrs: false
};
</script>
<form-group :validator="$v.name" attribute="Name">
<mu-text-field type="password" v-model="name" prop="name"/>
</form-group>
Usage with Quasar
Quasar offers the q-field
component, that has an error and a message prop. We can leverage those and create
an invisible wrapper around it.
<template>
<q-field
v-bind="$attrs"
:label="label"
:error="hasErrors"
:error-label="firstErrorMessage"
>
<slot/>
</q-field>
</template>
<script>
import { singleErrorExtractorMixin } from "vuelidate-error-extractor";
export default {
name: "FormGroup",
extends: singleErrorExtractorMixin,
inheritAttrs: false
};
</script>
Then we can register it globally and use it with q-input
or any other form element.
<form-group
:validator="$v.form.email"
label="Email with wrapper"
>
<q-input
v-model="form.email"
placeholder="Input Email"
@input="$v.form.email.$touch()"
/>
</form-group>
Live Quasar example
Usage with Vue Material
Vue Material uses a very simple wrapper around its inputs to give them error state. Just wrap your input with an md-field
and give it a class of md-invalid
and you are done.
<template>
<md-field :class="{ 'md-invalid': hasErrors }">
<label> {{ label }} </label>
<slot/>
<span class="md-error" v-if="hasErrors">{{ firstErrorMessage }}</span>
</md-field>
</template>
<script>
import { singleErrorExtractorMixin } from "vuelidate-error-extractor";
export default {
extends: singleErrorExtractorMixin
};
</script>
Usage is straight forward
<form-group :validator="$v.form.email" label="Email Input">
<md-input
v-model="form.email"
@input="$v.form.email.$touch()"
/>
</form-group>
Live Vue Material Example
Usage with BootstrapVue
Bootstrap Vue offers the b-form-group
component with invalid-feedback
and state
props. It expects an error message and a boolean state, so we pass the firstErrorMessage
and the isValid
.
Added bonus is the scoped slot with attrs
and listeners
props. You can skip those, but they can reduce boilerplate in the future.
<template>
<b-form-group
:invalid-feedback="firstErrorMessage"
:state="isValid"
:label="label"
>
<slot
:attrs="{ state: isValid }"
:listeners="{ input: () => preferredValidator.$touch() }"
/>
</b-form-group>
</template>
<script>
import { singleErrorExtractorMixin } from "vuelidate-error-extractor";
export default {
name: "FormElement",
extends: singleErrorExtractorMixin
};
</script>
Usage is simple
<form-group :validator="$v.form.email" label="Email with wrapper">
<b-form-input
slot-scope="{ attrs, listeners }"
v-bind="attrs"
v-on="listeners"
v-model="form.email"
/>
</form-group>
Live Bootstrap Vue Example
Usage with Buefy
Buefy exposes the b-field
component, which has type
and message
props. We supply a type of is-danger
and the firstErrorMessage
to these respectively.
<template>
<b-field
:label="label"
:custom-class="customClass"
:type="type"
:message="firstErrorMessage"
>
<slot/>
</b-field>
</template>
<script>
import { singleErrorExtractorMixin } from "vuelidate-error-extractor";
export default {
extends: singleErrorExtractorMixin,
computed: {
type() {
return this.hasErrors ? "is-danger" :
this.isValid ? "is-success" :
null
},
customClass() {
return this.hasErrors ? "has-text-danger" :
this.isValid ? "has-text-success" :
null
}
}
}
</script>
And we use like normal
<form-group
:validator="$v.form.email"
label="Email with wrapper"
>
<b-input
v-model="form.email"
@input="$v.form.email.$touch()"
/>
</form-group>
Live Buefy example
Usage with Vuesax
Vuesax just has one input the vs-input
that accepts vs-danger
and vs-success
as booleans props. You can provide vs-danger-text
prop which is waits for a string.
<template>
<vs-input
v-model="model"
:vs-label="label"
:vs-danger="hasError"
:vs-success="isValid"
:vs-danger-text="firstErrorMessage"
/>
</template>
<script>
import { singleErrorExtractorMixin } from "vuelidate-error-extractor";
export default {
name: 'FormInput',
extends: singleErrorExtractorMixin,
props: {
value: {
type: [Object, String, Number],
default: null
}
},
computed: {
model : {
get () {
return this.value
},
set (value) {
this.$emit('input', value)
}
}
}
};
</script>
Use it like so:
<form-input
:validator="$v.form.name"
label="Name field"
v-model="$v.form.name"
/>