Skip to content
This repository was archived by the owner on Dec 25, 2017. It is now read-only.

Reset validation for a single form field #363

Open
wants to merge 4 commits into
base: 2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
570 changes: 340 additions & 230 deletions dist/vue-validator.common.js

Large diffs are not rendered by default.

572 changes: 341 additions & 231 deletions dist/vue-validator.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions dist/vue-validator.min.js

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions example/reset/single/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>validation result resetting example</title>
<script src="../../../node_modules/vue/dist/vue.min.js"></script>
<script src="../../../dist/vue-validator.min.js"></script>
<style>
.errors { color: red; }
</style>
</head>
<body>
<div id="app">
<validator name="validation1">
<form novalidate>
<div class="username-field">
<label for="username">username:</label>
<input id="username" type="text" v-validate:username="['required']">
<button type="button" @click="onReset('username')">Reset Validation</button>
</div>
<div class="password-field">
<label for="password">password:</label>
<input id="password" type="password" v-validate:password="{ required: true, maxlength: 15 }">
<button type="button" @click="onReset('password')">Reset Validation</button>
</div>
<div class="errors">
<p v-if="$validation1.username.required">Your name is required.</p>
<p v-if="$validation1.password.required">Your password is required.</p>
<p v-if="$validation1.password.maxlength">Your password is too long.</p>
</div>
<input type="submit" value="send" v-if="$validation1.valid">
<button type="button" @click="onResetAll">Reset Validation</button>
</form>
<pre>{{ $validation1 | json }}</pre>
</validator>
</div>
<script>
new Vue({
el: '#app',
methods: {
onReset: function (field) {
this.$resetField(field)
},
onResetAll: function () {
this.$resetValidation()
}
}
})
</script>
</body>
</html>
30 changes: 30 additions & 0 deletions src/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export default class Validator {
// define the validation resetting meta method to vue instance
this._defineResetValidation()

// define the validation resetting for a single field
this._defineResetField()

// define the validate manually meta method to vue instance
this._defineValidate()

Expand All @@ -56,6 +59,8 @@ export default class Validator {
delete vm['$validate']
vm.$resetValidation = null
delete vm['$resetValidation']
vm.$resetField = null
delete vm['$resetField']
vm._validatorMaps[this.name] = null
delete vm._validatorMaps[this.name]
vm[this.name] = null
Expand Down Expand Up @@ -193,6 +198,23 @@ export default class Validator {
}
}

_defineResetField () {
this._dir.vm.$resetField = (...args) => {
let field = null
let cb = null

each(args, (arg, index) => {
if (typeof arg === 'string') {
field = arg
} else if (typeof arg === 'function') {
cb = arg
}
})

this._resetField(field, cb)
}
}

_defineValidate () {
this._dir.vm.$validate = (...args) => {
let field = null
Expand Down Expand Up @@ -255,6 +277,14 @@ export default class Validator {
|| (this._radioValidations[field] && this._radioValidations[field].validation)
}

_resetField (field, cb) {
var validation = this._getValidationFrom(field)
if (validation) {
validation.reset()
}
this._validates(cb)
}

_resetValidation (cb) {
each(this.validations, (validation, key) => {
validation.reset()
Expand Down
1 change: 1 addition & 0 deletions test/specs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ require('./checkbox')
require('./radio')
require('./select')
require('./reset')
require('./reset-single')
require('./validate')
require('./initial')
require('./async')
Expand Down
4 changes: 2 additions & 2 deletions test/specs/issues.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ describe('github issues', () => {
trigger(foo, 'blur')
vm.$nextTick(() => {
assert(vm.$validator1.field1.required === false)
assert(vm.$validator1.field1.minlength === true)
assert(vm.$validator1.field1.valid === false)
assert(vm.$validator1.field1.minlength === false)
assert(vm.$validator1.field1.valid === true)
assert(vm.$validator1.field1.touched === true)
assert(vm.$validator1.field1.dirty === true)
assert(vm.$validator1.field1.modified === true)
Expand Down
264 changes: 264 additions & 0 deletions test/specs/reset-single.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
import assert from 'power-assert'
import Vue from 'vue'
import { trigger } from '../../src/util'


describe('reset single field', () => {
let el, vm

beforeEach(() => {
el = document.createElement('div')
})


describe('text', () => {
beforeEach((done) => {
el.innerHTML = `
<validator name="validator1">
<form novalidate>
<input type="number" v-validate:field1="{ required: true, min: 0, max: 10 }">
<input type="text" value="hello" v-validate:field2="{ minlength: 4 }">
</form>
</validator>
`
vm = new Vue({ el })
vm.$nextTick(done)
})

it('should be reset', (done) => {
assert(vm.$validator1.field1.required)
assert(vm.$validator1.field1.min === false)
assert(vm.$validator1.field1.max === false)
assert(vm.$validator1.field1.valid === false)
assert(vm.$validator1.field1.dirty === false)
assert(vm.$validator1.field1.modified === false)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field2.minlength === false)
assert(vm.$validator1.field2.valid === true)
assert(vm.$validator1.field2.dirty === false)
assert(vm.$validator1.field2.modified === false)
assert(vm.$validator1.field2.touched === false)
assert(vm.$validator1.valid === false)
assert(vm.$validator1.dirty === false)
assert(vm.$validator1.modified === false)
assert(vm.$validator1.touched === false)
// change
const field1 = el.getElementsByTagName('input')[0]
const field2 = el.getElementsByTagName('input')[1]
field1.value = '200'
field2.value = 'World'
trigger(field1, 'input')
trigger(field1, 'blur')
trigger(field2, 'input')
trigger(field2, 'blur')
vm.$nextTick(() => {
// reset
vm.$resetField('field1', () => {
assert(vm.$validator1.field1.required === false)
assert(vm.$validator1.field1.min === false)
assert(vm.$validator1.field1.max === true)
assert(vm.$validator1.field1.valid === false)
assert(vm.$validator1.field1.dirty === false)
assert(vm.$validator1.field1.modified === false)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field2.minlength === false)
assert(vm.$validator1.field2.valid === true)
assert(vm.$validator1.field2.dirty === true)
assert(vm.$validator1.field2.modified === true)
assert(vm.$validator1.field2.touched === true)
assert(vm.$validator1.valid === false)
assert(vm.$validator1.dirty === true)
assert(vm.$validator1.modified === true)
assert(vm.$validator1.touched === true)
done()
})
})
})
})


describe('checkbox', () => {
beforeEach((done) => {
el.innerHTML = `
<validator name="validator1">
<form novalidate>
<input type="checkbox" value="foo" v-validate:field1="{ required: true, minlength: 1 }">
<input type="checkbox" value="bar" v-validate:field1>
</form>
</validator>
`
vm = new Vue({ el })
vm.$nextTick(done)
})

it('should be reset', (done) => {
assert(vm.$validator1.field1.required)
assert(vm.$validator1.field1.minlength === true)
assert(vm.$validator1.field1.valid === false)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field1.dirty === false)
assert(vm.$validator1.field1.modified === false)
assert(vm.$validator1.valid === false)
assert(vm.$validator1.dirty === false)
assert(vm.$validator1.modified === false)
assert(vm.$validator1.touched === false)
// change
const checkbox1 = el.getElementsByTagName('input')[0]
const checkbox2 = el.getElementsByTagName('input')[1]
checkbox1.checked = true
checkbox2.checked = true
trigger(checkbox1, 'change')
trigger(checkbox1, 'blur')
trigger(checkbox2, 'change')
trigger(checkbox2, 'blur')
vm.$nextTick(() => {
// reset
vm.$resetField('field1', () => {
assert(vm.$validator1.field1.required === false)
assert(vm.$validator1.field1.minlength === false)
assert(vm.$validator1.field1.valid === true)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field1.dirty === false)
assert(vm.$validator1.field1.modified === false)
assert(vm.$validator1.valid === true)
assert(vm.$validator1.dirty === false)
assert(vm.$validator1.modified === false)
assert(vm.$validator1.touched === false)
done()
})
})
})
})


describe('radio', () => {
beforeEach((done) => {
el.innerHTML = `
<validator name="validator1">
<form novalidate>
<fieldset>
<label for="radio1">radio1</label>
<input type="radio" id="radio1" name="r1" checked value="foo" v-validate:field1="{ required: true }">
<label for="radio2">radio2</label>
<input type="radio" id="radio2" name="r1" value="bar" v-validate:field1>
</fieldset>
<fieldset>
<label for="radio3">radio3</label>
<input type="radio" id="radio3" name="r2" value="buz" v-validate:field2="{ required: true }">
<label for="radio4">radio4</label>
<input type="radio" id="radio4" name="r2" value="hoge" v-validate:field2>
</fieldset>
</form>
</validator>
`
vm = new Vue({ el })
vm.$nextTick(done)
})

it('should be reset', (done) => {
// default
assert(vm.$validator1.field1.required === false)
assert(vm.$validator1.field1.valid === true)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field1.dirty === false)
assert(vm.$validator1.field1.modified === false)
assert(vm.$validator1.field2.required)
assert(vm.$validator1.field2.valid === false)
assert(vm.$validator1.field2.touched === false)
assert(vm.$validator1.field2.dirty === false)
assert(vm.$validator1.field2.modified === false)
assert(vm.$validator1.valid === false)
assert(vm.$validator1.touched === false)
assert(vm.$validator1.dirty === false)
assert(vm.$validator1.modified === false)
// change
const radio2 = el.getElementsByTagName('input')[1]
const radio3 = el.getElementsByTagName('input')[2]
radio2.checked = true
radio3.checked = true
trigger(radio2, 'change')
trigger(radio2, 'blur')
trigger(radio3, 'change')
trigger(radio3, 'blur')
vm.$nextTick(() => {
// reset
vm.$resetField('field1', () => {
assert(vm.$validator1.field1.required === false)
assert(vm.$validator1.field1.valid === true)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field1.dirty === false)
assert(vm.$validator1.field1.modified === false)
assert(vm.$validator1.field2.required === false)
assert(vm.$validator1.field2.valid === true)
assert(vm.$validator1.field2.touched === true)
assert(vm.$validator1.field2.dirty === true)
assert(vm.$validator1.field2.modified === true)
assert(vm.$validator1.valid === true)
assert(vm.$validator1.touched === true)
assert(vm.$validator1.dirty === true)
assert(vm.$validator1.modified === true)
done()
})
})
})
})


describe('select', () => {
beforeEach((done) => {
el.innerHTML = `
<validator name="validator1">
<form novalidate>
<select multiple v-validate:lang="{ required: true, minlength: 2 }">
<option value="en">english</option>
<option value="ja">japanese</option>
<option value="zh">chinese</option>
<option value="fr">french</option>
<option value="de">German</option>
</select>
</form>
</validator>
`
vm = new Vue({ el })
vm.$nextTick(done)
})

it('should be reset', (done) => {
// default
assert(vm.$validator1.lang.required)
assert(vm.$validator1.lang.minlength === true)
assert(vm.$validator1.lang.valid === false)
assert(vm.$validator1.lang.touched === false)
assert(vm.$validator1.lang.dirty === false)
assert(vm.$validator1.lang.modified === false)
assert(vm.$validator1.valid === false)
assert(vm.$validator1.touched === false)
assert(vm.$validator1.dirty === false)
assert(vm.$validator1.modified === false)
// change
const select = el.getElementsByTagName('select')[0]
const option2 = el.getElementsByTagName('option')[1]
const option3 = el.getElementsByTagName('option')[2]
option2.selected = true
option3.selected = true
trigger(select, 'change')
trigger(select, 'blur')
vm.$nextTick(() => {
// reset
vm.$resetField('lang', () => {
assert(vm.$validator1.lang.required === false)
assert(vm.$validator1.lang.minlength === false)
assert(vm.$validator1.lang.valid === true)
assert(vm.$validator1.lang.touched === false)
assert(vm.$validator1.lang.dirty === false)
assert(vm.$validator1.lang.modified === false)
assert(vm.$validator1.valid === true)
assert(vm.$validator1.touched === false)
assert(vm.$validator1.dirty === false)
assert(vm.$validator1.modified === false)
done()
})
})
})
})
})