Skip to content

Commit dc2487e

Browse files
committed
feat(QForm): validate respecting DOM order
1 parent 0ad4985 commit dc2487e

File tree

6 files changed

+56
-47
lines changed

6 files changed

+56
-47
lines changed

ui/dev/src/pages/form/form.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ export default {
213213
this.$q.notify('submit')
214214
console.log('@submit')
215215
216-
evt.target.submit()
216+
// evt.target.submit()
217217
},
218218
219219
onReset () {

ui/src/components/field/QField.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ export default Vue.extend({
129129
shouldRenderBottom () {
130130
return this.bottomSlots === true ||
131131
this.hint !== void 0 ||
132-
this.rules !== void 0 ||
132+
this.hasRules === true ||
133133
this.counter === true ||
134134
this.error !== null
135135
},

ui/src/components/form/QForm.js

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import Vue from 'vue'
22

33
import { stopAndPrevent } from '../../utils/event.js'
44
import { slot } from '../../utils/slot.js'
5-
import { getAllChildren } from '../../utils/vm.js'
65

76
export default Vue.extend({
87
name: 'QForm',
@@ -28,38 +27,36 @@ export default Vue.extend({
2827

2928
this.validateIndex++
3029

31-
const components = getAllChildren(this)
30+
const components = this.getValidationComponents()
31+
3232
const emit = (res, ref) => {
3333
this.$emit('validation-' + (res === true ? 'success' : 'error'), ref)
3434
}
3535

3636
for (let i = 0; i < components.length; i++) {
3737
const comp = components[i]
38+
const valid = comp.validate()
3839

39-
if (typeof comp.validate === 'function') {
40-
const valid = comp.validate()
41-
42-
if (typeof valid.then === 'function') {
43-
promises.push(
44-
valid.then(
45-
valid => ({ valid, comp }),
46-
error => ({ valid: false, comp, error })
47-
)
40+
if (typeof valid.then === 'function') {
41+
promises.push(
42+
valid.then(
43+
valid => ({ valid, comp }),
44+
error => ({ valid: false, comp, error })
4845
)
49-
}
50-
else if (valid !== true) {
51-
if (this.greedy === false) {
52-
emit(false, comp)
53-
54-
if (focus === true && typeof comp.focus === 'function') {
55-
comp.focus()
56-
}
46+
)
47+
}
48+
else if (valid !== true) {
49+
if (this.greedy === false) {
50+
emit(false, comp)
5751

58-
return Promise.resolve(false)
52+
if (focus === true && typeof comp.focus === 'function') {
53+
comp.focus()
5954
}
6055

61-
promises.push({ valid: false, comp })
56+
return Promise.resolve(false)
6257
}
58+
59+
promises.push({ valid: false, comp })
6360
}
6461
}
6562

@@ -101,10 +98,8 @@ export default Vue.extend({
10198
resetValidation () {
10299
this.validateIndex++
103100

104-
getAllChildren(this).forEach(comp => {
105-
if (typeof comp.resetValidation === 'function') {
106-
comp.resetValidation()
107-
}
101+
this.getValidationComponents().forEach(comp => {
102+
comp.resetValidation()
108103
})
109104
},
110105

@@ -138,9 +133,16 @@ export default Vue.extend({
138133

139134
focus () {
140135
const target = this.$el.querySelector('[autofocus], [data-autofocus]') ||
141-
[].find.call(this.$el.querySelectorAll('[tabindex]'), el => el.tabIndex > -1)
136+
Array.prototype.find.call(this.$el.querySelectorAll('[tabindex]'), el => el.tabIndex > -1)
142137

143138
target !== null && target !== void 0 && target.focus()
139+
},
140+
141+
getValidationComponents () {
142+
return Array.prototype.map.call(
143+
this.$el.getElementsByClassName('q-field'),
144+
field => field.__vue__
145+
).filter(c => c !== void 0 && typeof c.validate === 'function')
144146
}
145147
},
146148

ui/src/components/form/QForm.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@
112112
"__exemption": [ "examples" ]
113113
}
114114
}
115+
},
116+
117+
"getValidationComponents": {
118+
"desc": "Get array of children vue components that support validation",
119+
"returns": {
120+
"type": "Array",
121+
"desc": "Vue components that support Quasar validation API",
122+
"__exemption": [ "examples" ]
123+
},
124+
"addedIn": "v1.10.0"
115125
}
116126
}
117127
}

ui/src/mixins/validate.js

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,13 @@ export default {
2424
},
2525

2626
watch: {
27-
value (v) {
28-
if (this.rules === void 0) {
29-
return
27+
value () {
28+
if (
29+
this.hasRules === true &&
30+
(this.lazyRules !== true || this.isDirty !== true)
31+
) {
32+
this.validate()
3033
}
31-
if (this.lazyRules === true && this.isDirty !== true) {
32-
return
33-
}
34-
35-
this.validate(v)
3634
},
3735

3836
focused (focused) {
@@ -46,6 +44,12 @@ export default {
4644
},
4745

4846
computed: {
47+
hasRules () {
48+
return this.rules !== void 0 &&
49+
this.rules !== null &&
50+
this.rules.length > 0
51+
},
52+
4953
hasError () {
5054
return this.error === true || this.innerError === true
5155
},
@@ -88,7 +92,7 @@ export default {
8892
* - Promise (pending async validation)
8993
*/
9094
validate (val = this.value) {
91-
if (!this.rules || this.rules.length === 0) {
95+
if (this.hasRules !== true) {
9296
return true
9397
}
9498

@@ -104,6 +108,7 @@ export default {
104108
}
105109

106110
const m = msg || void 0
111+
107112
if (this.innerErrorMessage !== m) {
108113
this.innerErrorMessage = m
109114
}
@@ -180,9 +185,9 @@ export default {
180185
},
181186

182187
__triggerValidation () {
183-
if (this.isDirty === false && this.rules !== void 0) {
188+
if (this.isDirty === false && this.hasRules === true) {
184189
this.isDirty = true
185-
this.validate(this.value)
190+
this.validate()
186191
}
187192
}
188193
}

ui/src/utils/vm.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
import { isSSR } from '../plugins/Platform.js'
22

3-
export function getAllChildren (vm, children = []) {
4-
vm.$children.forEach(function (child) {
5-
children.push(child)
6-
child.$children.length > 0 && getAllChildren(child, children)
7-
})
8-
return children
9-
}
10-
113
export function getVmOfNode (el) {
124
for (let node = el; node !== null; node = node.parentNode) {
135
// node.__vue__ can be null if the instance was destroyed

0 commit comments

Comments
 (0)