semisleep / simple-vue-validator Goto Github PK
View Code? Open in Web Editor NEWA simple yet flexible validator library for vue.js
License: MIT License
A simple yet flexible validator library for vue.js
License: MIT License
Is there a way to disable the watcher and only validate on submit?
Hi author, i use vuex and my save action in $store of vuex, so how to validate in vuex actions ?
Hi, thx for awesome validator.
But im have trouble.. when in try validate multicomponent form, child not validate if this.validate has error below child component
for example
<component>
field=name
field=email
field=avatar
..
<child-component ref="child">
field=isProduct,
field=isDemo,
field=allFiles,
<products-component v-if="isProduct" ref="products">
field=files
<product-add-component>
</products-component>
field=anotherData0
....
field=anotherDataN
<demos-component v-if="isDemo" ref="demos">
field=demos
<demo-add-component>
</demos-component>
</child-component>
field=agree
</component>
in child-component i have validate rules like
'allFiles': function (value) {
return Validator.custom(function () {
if (this.isProduct) {
return this.$refs.products.$validate().then(function(success){
if (!success)
return 'no products';
});
}
}, this)
},
in products component i have validate rules like
'files' : function(value) {
return Validator.value(value).greaterThan(0);
}
so then in main component im use
child = this.$refs.child.$validate();
component = this.$validate();
Promise.all([child, component]).then(function(results){
})
errors from child component show if field=agree is valid
and not show if field=agree invalid
Thanks for such great library.
I want to know I have added validation on one field based on value of other field. validation is added perfectly. Now how can i remove that validation rule when dependent field value going to be changed.
My requirement is if one field contains some value at that time other field is required and for some value I don't want that field is required.
Hi all,
I know the project is dormant currently but perhaps someone might know why async validations that is "overwritten" by a second async call succeeds eg.
let success = await $validate() will return true if an async validation is triggered again before the original event completes.
If my explanation is a bit confusing the lines in question is here:
simple-vue-validator/src/validation-bag.js
Lines 238 to 242 in 0ee438e
specifically line 242 returns false, meaning there is no error. Isn't it safer to return true rather?
Kind regards
Bob
Hello! How can I call $validate() in the root component for children validate?
I know it isn't a huge dependency, but it would be nice to let users do their own polyfilling, especially for something like Promise
, which is pretty widely implemented in browsers.
Is there such a two forms in one page but separately?
Hey, again! 😄
I was looking through the docs again and couldn't find anything on customizing the error messages for the default validators like .required()
and .email()
. There is Validator.extendTemplates()
, but I get the impression that that makes the changes globally. I'm looking to make changes to the error messages on a per-component and per-field basis. Using a custom validator gets the job done, but it's very verbose. See the screenshot below for an example.
Notice how most of the code is just replicating .required()
and .email()
.
What do you think? I'm picturing adding an errors
key (or similar) to the component, the same way we add the validators
key. Here is a per-field example:
export default {
name: 'component',
errors: {
'object.property1.email': 'That doesn\'t look like a valid email address.',
'object.property1.required': 'We really need you to enter your email.',
'object.property2.required': 'Yeah. We need this one too.',
},
validators: {
'object.property1': function (value) {
return Validator.value(value).required().email();
},
'object.property2': function (value) {
return Validator.value(value).required();
},
},
};
Notice how each key in errors
is prefixed by the field name. In the case where you want to change the error message on a per-component basis, just leave off the field name. Example:
export default {
name: 'component',
errors: {
'required': 'We need you to fill out this field.',
'object.property1.email': 'That doesn\'t look like a valid email address.',
},
validators: {
'object.property1': function (value) {
return Validator.value(value).required().email();
},
'object.property2': function (value) {
return Validator.value(value).required();
},
},
};
Thoughts?
Here is the code sample:
import axios from 'axios';
import {mixin as ValidatorMixins, Validator } from 'simple-vue-validator';
export default {
mixins: [ValidatorMixins],
data: function () {
return {
isValidated: false,
listTypes: [],
listType: ""
};
},
validations: {
listType (value) {
return Validator.value(value).require();
}
},
created: function () {
axios.get("/list-types").then((response) => {
this.listTypes = response.data;
}).catch((error) => {
this.$notify({
type: 'error',
text: 'Can not get list of type: ' + error.response.statusText
});
});
},
methods: {
upload () {
this.$validate()
.then((success)=> {
if (!success) {
this.$notify({
type: 'error',
text: 'Error when sending the file. Check input for details'
})
}
this.isValidated = true;
});
}
}
}
And here is the call stack:
vue.esm.js:1696 TypeError: Cannot read property '_validate' of undefined
at VueComponent.$validate (mixin.js:114)
at VueComponent.boundFn [as $validate] (vue.esm.js:189)
at VueComponent.upload (upload.vue:111)
at Proxy.boundFn (vue.esm.js:189)
at Proxy.render (upload.vue?8bf2:73)
at VueComponent.Vue._render (vue.esm.js:4427)
at VueComponent.updateComponent (vue.esm.js:2741)
at Watcher.get (vue.esm.js:3084)
at Watcher.run (vue.esm.js:3161)
at flushSchedulerQueue (vue.esm.js:2927)
at Array.<anonymous> (vue.esm.js:1792)
at flushCallbacks (vue.esm.js:1713)
at <anonymous>
The project is missing a test suite and therefore lacks user trust. I have put together a simple idea of how the tests should be structured.
import {expect} from 'chai'
import Rule from '../src/rule'
function makeRule(value) {
return new Rule().value(value)
}
function hasErrors(rule) {
return rule._messages.length > 0
}
describe('Rules', () => {
describe('integer', () => {
it('string equivalents are considered integers', () => {
expect(hasErrors(makeRule('1').integer())).to.be.false
expect(hasErrors(makeRule('0').integer())).to.be.false
expect(hasErrors(makeRule('-1').integer())).to.be.false
})
it('will fail if a float value is provided', () => {
expect(hasErrors(makeRule('1.1').integer())).to.be.true
expect(hasErrors(makeRule('0.').integer())).to.be.true
})
it('empty values are considered invalid', () => {
expect(hasErrors(makeRule(null).integer())).to.be.true
})
})
})
Let me know if this is something you would want to expand upon and can even help write and run the required tests.
Some way of check if the form is valid if all required inputs was touched and they're all valid
When using the mixin (as documented here), there is no apparent way to set the interaction mode. It seems the entire plugin have to be imported first, so that the plugin method setMode
can be called before the mixin is used - perhaps this should be documented?
Example:
import SimpleVueValidator from 'simple-vue-validator'
SimpleVueValidator.setMode('conservative')
const Validator = SimpleVueValidator.Validator
export default {
name: 'MyComponent',
mixins: [SimpleVueValidator.mixin],
...
My custom method validation (async) prevents built-in rules from being tested. It would be nice if the custom validation rule would be done only if the built-in rules are validated.
I tried this without success.
"bailleur.nom": {
debounce: 800,
validator: function(value) {
return this.$RulesFor(value)
.required()
.maxLength(100)
.custom(() => {
if (!this.validation.hasError("bailleur.nom")) {
let filter = [
{ key: "id_ne", value: this.bailleur.id },
{ key: "nom", value: value }
];
return this.isBailleurNomUnique(filter)
.then(() => {
return "Le bailleur existe déjà.";
})
.catch(() => {});
}
});
}
},
When I use debounce option, the field is validated automatically as required while I have not touched and edited the field.
"bailleur.nom": {
debounce: 500,
validator: function(value) {
return this.$Validator
.value(value)
.required()
.maxLength(100)
}
}
Kinda like how $validate
works, only reset the field or array of fields passed.
I've got a select input that triggers conditional validations. The first item is intentionally left blank and passes a value of undefined to the validator
this generates an error:
'formData.country': function (value) {
return Validator.value(value).required();
},
this does not, because the value passed cannot be null or undefined (or 0 or false in this case)
'formData.country': function (value) {
return Validator.value(value || '').required();
},
It would be helpful, I think,to have the possibility of passing an undefined or null handled internally.
This is my validator
import propNameExistValidation from '../../../validators/checkPropertyNameExist';
...
validators: {
'propertyName,propertyUuid':{
debounce: 500, // in milliseconds
validator: function (propertyName,propUuid) {
return Validator.value(propertyName)
.required()
.custom(propNameExistValidation(propertyName,propUuid));
}
}
},
And this is my propNameExistValidation.js
export default function propNameExistValidation(propertyName,propertyUuid) {
console.log(propertyName,propertyUuid);
if (!Validator.isEmpty(propertyName)) {
return axios.post('/myApi', {
property_name: propertyName,
propertyUuid:propertyUuid
}).then((response) => {
let valid = (response.data.valid == 'true');
if(!valid){
return Vue.i18n.translate('errors.propertyNameExist');
}
});
}
};
EDIT:
If i use function directly inside custom parameter, it works just fine.
validators: {
'propertyName,propertyUuid':{
debounce: 500, // in milliseconds
validator: function (propertyName,propUuid) {
return Validator.value(propertyName)
.required()
.custom(function (propertyName,propUuid) {
return axios.post('/myApi', {
property_name: propertyName,
propertyUuid:propUuid
}).then((response) => {
// return response.data.valid;
let valid = (response.data.valid == 'true');
if(!valid){
return Vue.i18n.translate('errors.propertyNameExist');
}
});
});
}
}
},
using the float() validator
it'll pass
1 -> ok
1.3 -> ok
1a -> NOT OK
1bdef -> NOT OK
1 2 3 -> NOT OK
it'll fail
a -> ok
Hi there!
I reviewed the package and got to say that it's the most clean and nice way to validate forms, I love it!
However, there are some cases when the frontend validation passes, but the backend one will fail. For example, I got many users registering at the same time, and there might be some collisions with the emails, so I check on the backend API (Laravel) once again if the whole submitted form is valid. If not, it returns a normal 422 from Laravel with the error messages bag.
My question here is how to trigger those validation errors to display on the frontend? I'd like to do something like:
this.$invalidate([
{ email: 'This email is already taken' },
{ username: 'This username is already taken' }
]);
Basically a way to trigger custom error messages on the fly. Is that possible at the moment?
Is there a way so we can access the vue instance inside a validator?
I'm using a combination of client and server side validation
a validator object may look like this:
validator: (value) => {
return Validator
.value(value)
.required()
.custom(() => {
// my async validation
})
}
the problem is that the async validation happens in parallel with the required() validator, meaning that I"m sending API requests even though i know they will fail.
Instead I end up implementing all the validations, such as required and min length, within the custom.
an option to have request run in series would help
debounce: 500, cache: true, sequntial: false|true ...
I'm getting this error:
[Vue warn]: Error in watcher "coords.lat"
(found in component <Setup> at C:\Users\glen\Source\Repos\Badi-Web3\src\pages\LocationSetup.vue)
VM65704:27 Error: Validator.value not set
at Rule._checkValue (eval at <anonymous> (http://localhost:8080/js/app.js:1763:1), <anonymous>:42:11)
at Rule.required (eval at <anonymous> (http://localhost:8080/js/app.js:1763:1), <anonymous>:48:20)
at VueComponent.coordsLat (eval at <anonymous> (http://localhost:8080/js/app.js:2004:1), <anonymous>:34:37)
at VueComponent.eval (eval at <anonymous> (http://localhost:8080/js/app.js:2334:1), <anonymous>:41:32)
at eval (eval at <anonymous> (http://localhost:8080/js/app.js:2334:1), <anonymous>:95:20)
at Array.map (native)
at VueComponent.$validate (eval at <anonymous> (http://localhost:8080/js/app.js:2334:1), <anonymous>:94:32)
at VueComponent.boundFn [as $validate] (eval at <anonymous> (http://localhost:8080/js/app.js:736:1), <anonymous>:127:12)
at VueComponent.checkValidation (eval at <anonymous> (http://localhost:8080/js/app.js:2004:1), <anonymous>:56:12)
at VueComponent.boundFn [as checkValidation] (eval at <anonymous> (http://localhost:8080/js/app.js:736:1), <anonymous>:127:12)
at VueComponent.coordsLat (eval at <anonymous> (http://localhost:8080/js/app.js:2004:1), <anonymous>:45:12)
at Watcher.run (eval at <anonymous> (http://localhost:8080/js/app.js:736:1), <anonymous>:1735:19)
at flushSchedulerQueue (eval at <anonymous> (http://localhost:8080/js/app.js:736:1), <anonymous>:1539:13)
at Array.eval (eval at <anonymous> (http://localhost:8080/js/app.js:736:1), <anonymous>:471:20)
at nextTickHandler (eval at <anonymous> (http://localhost:8080/js/app.js:736:1), <anonymous>:420:16)
Some extracts from the .vue file:
<template>
<input type="number" min="-85" max="85" step="any" v-model="coords.lat" :class="{'has-error': validation.hasError('coords.lat')}">
</template>
<script>
...
data() { return coords: {lat: 0, long: 0} },
validators: {
'coords.lat': function (value) {
return Validator.value(value).required().float().between(-85, 85);
},
'coords.long': function (value) {
return Validator.value(value).required().float().between(-180, 180);
},
},
watch: {
'coords.lat': function (n, o) {
this.checkValidation()
},
'coords.long': function (n, o) {
this.checkValidation()
}
},
methods: {
checkValidation() {
this.$validate()
.then(function (success) {
if (success) {
alert('Validation succeeded!');
}
});
}
</script>
(The file works fine without validation... the above is a simplified extract to show here.)
The value
parameter is undefined. Any ideas why?
If I replace the return Validator.value(....
with return true
then I get:
TypeError: rule.field is not a function
If I entirely remove the validators: {}
section, then I get a popup with 'Validation succeeded!'.
I'm using Vue2
I ran
npm install --save simple-vue-validator
in my main.js file i have:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import BootstrapVue from 'bootstrap-vue'
import SimpleVueValidation from 'simple-vue-validator';
Vue.use(SimpleVueValidation);
Vue.use(BootstrapVue);
Vue.config.productionTip = false;
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
new Vue({
router,
render: h => h(App)
}).$mount('#app')
In my component script section I added:
validators: {
'form.email': function (value) {
return Validator.value(value).required().email();
}
},
and I run this on my submit:
this.$validate()
.then(function(success) {
if (success) {
alert('Validation succeeded!')
}
});
This looks like a great library but it's not working for me =/
Coul you tell me how to focus an input when there's an error on it?
the ability to add an error AFTER an asynch function is helpful and possible using
this.validation.addError('myField', messages.MY_ERROR);
would be helpful to include it in documentation
Is it possible to load simple-vue-validator from a CDN or some other method which does not require webpack? I'm using Rollup in my current project and am unable to import simple-vue-validator.
I would like a required field to be validated when it was left unmodified. There is currently no behavior provided for this purpose. Could you implement this or tell me how to implement this default behavior?
嗨,你好。
在使用的时候有些场景需要设置validators,例如表单是异步拉取渲染的,就是说在mounted之后的ajax请求才获取表单有什么字段。
是不是能够提供设置或者重置validators的功能呢?
我看了下mixin.js里面的代码,vm.$options.validators是用作初始化的,不知道提供一个resetValidators方法是否可行?
In mixin, set validators on beforeMount (or mount) hook
beforeMount: function () {
this.$setValidators(this.$options.validators);
if (this.validation) {
// set vm to validation
this.validation._setVM(this);
}
},
Let's say we want to get an initial state from vuex store and put it into component data. We will do this at component creation. If the validators are set on created hook, in interactive mode It will fire validation directly because data changed and watchers are already observing data.
However, if validators are set in beforeMount or mount hook, It will not fire validation because data have been initialized before.
In addition, there is no need to set validators until component is mounted because user is not able to interact with data until that moment.
I did that change and It solved the problem.
I will not do a pull request for a small change like that. 😄
Could you tell me how to create a global custom rule and add it to validator prototype ?
Best regards
If the input has a value of 2.9 or 2.99, etc. parseInt(value) returns 2, so the value is converted to an integer, but it is not validated to make sure the value passed in was an integer.
Rule.prototype.integer = function (message) {
var value = this._checkValue();
if (!utils.isEmpty(value)) {
var number = parseInt(value);
if (utils.isNaN(number)) {
this._messages.push(message || this.templates.integer);
}
// ADD THIS CHECK
else if (number !== Number(value)) { // 2 !=== 2.9
this._messages.push(message || this.templates.integer);
}
}
return this;
};
I think the float validator has the same issue.
Is it possible to do validation on blur?
Seems like like it is a better user experience to validate on blur than as the user is typing.
It would be great if there was a way to provide validation scopes to the validators. This would give the user an easier way to validate groups of form fields. A full form, a form in a dialog/prompt etc. I think it would be more convenient to call $validate('scopeA')
and $validate('scopeB')
instead of having to define an array of form fields for one-off validations. Not passing any arguments to the $validate() method could validate all of the scopes by default.
I typically have forms with multiple independent dialogs that contain sub forms that need independent validation. I could break them out into their own components and have them validate at the component level, but that's a lot of work for multiple 3-5 input forms that live inside a small dialog.
Scopes could be defined on the validators. Something along the lines of:
validators: {
scopeA: {
'submittal.lineNo' (value) {
return Validator.value(value).required().digit()
},
'submittal.description' (value) {
return Validator.value(value).required().maxLength(1000)
},
},
scopeB: {
'submittal.specSection' (value) {
return Validator.value(value).required().maxLength(255)
},
'submittal.class' (value) {
return Validator.value(value).required()
},
}
}
Keep up the great work on the library. It's much appreciated.
Hi,
Thanks for your light and terribly efficient plugin.
There is just one problem I faced with it: the validation seems to be forced to success, when validating multiple times, whereas an async validator fails.
Example:
The "Validation succeeded!" message appears, but was not expected.
Hi.
I really wanna use simple-vue-validator
in my project. But, I don't use NPM
.
So, can I user with <script src="(cdn/unpkg address)"></script>
?
If I use simple-vue-validator
, should I use NPM
?
We are trying to validate the maxLength on a text field that is optional. Sometimes it can be null or empty. However, we get an error message thrown from the this._checkValue that states Validator.value not set.
This messes with our unit tests because an error is thrown.
Rule.prototype._checkValue = function() { if (this._value === undefined) { throw new Error('Validator.value not set'); // this is the message } return this._value; };
We would prefer if the validation didn't make the assumption that a field is required. So, the following rule for maxLength would make sense:
Rule.prototype.maxLength = function (length, message) { var value = this._checkValue(); // change this to this._value - especially since the next line is checking for null or undefined or empty any way. if (!utils.isEmpty(value)) { var string = String(value); if (string.length > length) { this._messages.push(message || utils.format(this.templates.maxLength, length)); } } return this; };
Hello, when I have
requiredField: function(val) {
if (typeof val === 'undefined') {
val = '';
}
return Validator.value(val).required();
},
validators: {
'newTask.name': {
debounce: 200,
validator: Validator.requiredField,
},
newTask.due_date': Validator.dateSimple,
},
I am not able to reset field newTask.name
by calling this.validation.reset();
. But when I change to
validators: {
'newTask.name': Validator.requiredField,
'newTask.due_date': Validator.dateSimple,
},
everyhing works fine.
I was looking for a way to validate a single field earlier today and couldn't find anything documented. It looks like all of the bound validator functions are stored in an array and can't be requested by field name.
I think having the ability to validate a single field would be a great feature and I'm happy to do what i can to implement it if you're busy.
P.S. Amazing project! Finding a good validation library for Vue 2.0 has been rough, but I'm really enjoying simple-vue-validator
.
Im using the vue onsen framework and started to implement simple vue validator. Here is my code
<v-ons-list modifier="inset">
<v-ons-list-item
modifier="longdivider"
:name="'question-' + $indexParent"
v-for="(choice, key, $index) in questionnaire['doc']['choices']"
:key="key"
tappable
>
<label class="left">
<v-ons-radio
:input-id="$indexParent + '-' + $index"
:value="key"
v-model="chosenAnswers[$indexParent]"
>
</v-ons-radio>
</label>
<label class="center" :for="$indexParent + '-' + $index">
{{key}}.{{choice}}
</label>
</v-ons-list-item>
<div class="message">{{ validation.firstError('chosenAnswers') }}</div>
</v-ons-list>
Hi all,
I'm looking to implement validation feedback as follows:
Out of the box, simple vue validator seems to support either 1 or 1.1 depending on if the lazy modifier is used. But switching between lazy and instant doesn't seem possible.
Some validation libraries provide flags for each validation binding e.g. Vee Validate has these flags:
from https://baianat.github.io/vee-validate/guide/flags.html:
touched: indicates that the field has been touched or focused.
untouched: indicates that the field has not been touched nor focused.
dirty: indicates that the field has been manipulated.
pristine: indicates that the field has not been manipulated.
valid: indicates that the field has passed the validation.
invalid: indicates that the field has failed the validation.
pending: indicates that the field validation is in progress.
validated: indicates that the field has been validated at least once by an event or manually using validate() or validateAll().
changed: indicates that the field value has been changed (strict check).
With these type of flags one can implement the above validation pattern like this :
// Only show error if the field hasbeen modified and visited (focus lost)
methods: canShowError(name) {
return validation.getField(name).flags.dirty &&
validation.getField(name).flags.visited &&
validation.getField(name).flags.invalid
}
<div class="message"v-if="canShowError('email')">
<div class="message">{{ validation.firstError('email') }}</div>
</div>
What do you think?
Kind regards
Bob
Hello,
Regarding mode
, I saw from the docs that you can set it two ways:
Vue.use(SimpleVueValidator, {mode: 'manual'};
SimpleVueValidator.setMode('conservative');
Is there a way to set it to a specific mode, but only within the scope of a component, and not globally?
Also can an individual field be configured to have a specific mode
?
Thanks.
It is possible to add validation rules after loading a set of fields. For example, if the set of fields depends on the select.
Need create method
validate: function() {
this.$setValidators(this.getValidatorRules());
this.$validate();
}
where getValidatorRules return object
{
'fieldName1' => function(){},
'fieldName2' => function(){},
}
Now it compiles with the complete lodash package (540 kB), that is, from my point of view, is unnecessary.
When trying to validate a undefined value on model throw an error. even thought docs says required() method suppose to check empty/null/undefined
null value by the way works fine
Demo form - http://simple-vue-validator.maijin.info/#dynamic_form not working, please fix.
`
onSubmit () {
const $this = this
this.$validate()
.then(function (success) {
if (success) {
if (confirm('Will you save?')) {
console.log(this, $this) // output
$this.createUser($this.form)
$this.hideModal()
}
} else {
alert('It's not valid')
}
})
},
// output : undefined, VueComponent { ...
`
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.