Skip to content

Commit 6125382

Browse files
authored
Merge pull request #129 from icebob/validations
Improve validations & bindings
2 parents 5ffcf20 + 19ecdbb commit 6125382

File tree

6 files changed

+322
-37
lines changed

6 files changed

+322
-37
lines changed

dev/full/app.vue

+7-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<div class="errors text-center">
1616
<div v-for="(item, index) in validationErrors" track-by="index" class="alert alert-danger">{{ item.field.label}}: <strong>{{ item.error }}</strong></div>
1717
</div>
18-
<vue-form-generator :schema="schema" :model="model" :options="formOptions" :multiple="selected.length > 1" ref="form" :is-new-model="isNewModel" @model-updated="modelUpdated"></vue-form-generator>
18+
<vue-form-generator :schema="schema" :model="model" :options="formOptions" :multiple="selected.length > 1" ref="form" :is-new-model="isNewModel" @model-updated="modelUpdated" @validated="onValidated"></vue-form-generator>
1919
</div>
2020
<div class="col-md-6">
2121
<pre v-if="model" v-html="prettyModel"></pre>
@@ -113,7 +113,11 @@
113113
clearSelection() {
114114
this.selected.splice(0);
115115
this.generateModel();
116-
},
116+
},
117+
118+
onValidated(res, errors) {
119+
console.log("VFG validated:", res, errors);
120+
},
117121
118122
generateModel() {
119123
if (this.selected.length == 1) {
@@ -185,7 +189,7 @@
185189
},
186190
187191
validate() {
188-
console.log("validate", this.$refs.form, this.$refs.form.validate());
192+
//console.log("validate", this.$refs.form, this.$refs.form.validate());
189193
return this.$refs.form.validate();
190194
},
191195

src/fields/abstractField.js

+18-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { get as objGet, each, isFunction, isString, isArray, isUndefined } from "lodash";
1+
import { get as objGet, each, isFunction, isString, isArray } from "lodash";
22

33
export default {
44
props: [
@@ -7,6 +7,12 @@ export default {
77
"disabled"
88
],
99

10+
data() {
11+
return {
12+
errors: []
13+
};
14+
},
15+
1016
computed: {
1117
value: {
1218
cache: false,
@@ -44,7 +50,7 @@ export default {
4450
this.$emit("model-updated", newValue, this.schema.model);
4551

4652
if (isFunction(this.schema.onChanged)) {
47-
this.schema.onChanged(this.model, newValue, oldValue, this.schema);
53+
this.schema.onChanged.call(this, this.model, newValue, oldValue, this.schema);
4854
}
4955

5056
if (this.$parent.options && this.$parent.options.validateAfterChanged === true){
@@ -56,7 +62,7 @@ export default {
5662
},
5763

5864
methods: {
59-
validate() {
65+
validate(calledParent) {
6066
this.clearValidationErrors();
6167

6268
if (this.schema.validator && this.schema.readonly !== true && this.disabled !== true) {
@@ -74,26 +80,27 @@ export default {
7480
let err = validator(this.value, this.schema, this.model);
7581
if (err) {
7682
if (isArray(err))
77-
Array.prototype.push.apply(this.schema.errors, err);
83+
Array.prototype.push.apply(this.errors, err);
7884
else if (isString(err))
79-
this.schema.errors.push(err);
85+
this.errors.push(err);
8086
}
8187
});
8288

8389
}
8490

8591
if (isFunction(this.schema.onValidated)) {
86-
this.schema.onValidated(this.model, this.schema.errors, this.schema);
92+
this.schema.onValidated.call(this, this.model, this.errors, this.schema);
8793
}
8894

89-
return this.schema.errors;
95+
let isValid = this.errors.length == 0;
96+
if (!calledParent)
97+
this.$emit("validated", isValid, this.errors, this);
98+
99+
return this.errors;
90100
},
91101

92102
clearValidationErrors() {
93-
if (isUndefined(this.schema.errors))
94-
this.$root.$set(this.schema, "errors", []); // Be reactive
95-
else
96-
this.schema.errors.splice(0); // Clear
103+
this.errors.splice(0);
97104
},
98105

99106
setModelValueByPath(path, value) {

src/formGenerator.vue

+37-15
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ div
99
i.icon
1010
.helpText(v-html='field.help')
1111
.field-wrap
12-
component(:is='getFieldType(field)', :disabled='fieldDisabled(field)', :model='model', :schema.sync='field', @model-updated='modelUpdated')
12+
component(:is='getFieldType(field)', :disabled='fieldDisabled(field)', :model='model', :schema.sync='field', @model-updated='modelUpdated', @validated="onFieldValidated")
1313
.buttons(v-if='buttonVisibility(field)')
1414
button(v-for='btn in field.buttons', @click='btn.onclick(model, field)', :class='btn.classes') {{ btn.label }}
1515
.hint(v-if='field.hint') {{ field.hint }}
16-
.errors(v-if='errorsVisibility(field)')
17-
span(v-for='(error, index) in field.errors', track-by='index') {{ error }}
16+
.errors(v-if='fieldErrors(field).length > 0')
17+
span(v-for='(error, index) in fieldErrors(field)', track-by='index') {{ error }}
1818
</template>
1919

2020
<script>
@@ -126,7 +126,7 @@ div
126126
// Get style classes of field
127127
getFieldRowClasses(field) {
128128
let baseClasses = {
129-
error: field.errors && field.errors.length > 0,
129+
error: this.fieldErrors(field).length > 0,
130130
disabled: this.fieldDisabled(field),
131131
readonly: this.fieldReadonly(field),
132132
featured: this.fieldFeatured(field),
@@ -153,7 +153,7 @@ div
153153
// Get disabled attr of field
154154
fieldDisabled(field) {
155155
if (isFunction(field.disabled))
156-
return field.disabled(this.model);
156+
return field.disabled.call(this, this.model, field, this);
157157
158158
if (isNil(field.disabled))
159159
return false;
@@ -164,7 +164,7 @@ div
164164
// Get required prop of field
165165
fieldRequired(field) {
166166
if (isFunction(field.required))
167-
return field.required(this.model);
167+
return field.required.call(this, this.model, field, this);
168168
169169
if (isNil(field.required))
170170
return false;
@@ -175,7 +175,7 @@ div
175175
// Get visible prop of field
176176
fieldVisible(field) {
177177
if (isFunction(field.visible))
178-
return field.visible(this.model);
178+
return field.visible.call(this, this.model, field, this);
179179
180180
if (isNil(field.visible))
181181
return true;
@@ -186,7 +186,7 @@ div
186186
// Get readonly prop of field
187187
fieldReadonly(field) {
188188
if (isFunction(field.readonly))
189-
return field.readonly(this.model);
189+
return field.readonly.call(this, this.model, field, this);
190190
191191
if (isNil(field.readonly))
192192
return false;
@@ -197,23 +197,42 @@ div
197197
// Get featured prop of field
198198
fieldFeatured(field) {
199199
if (isFunction(field.featured))
200-
return field.featured(this.model);
200+
return field.featured.call(this, this.model, field, this);
201201
202202
if (isNil(field.featured))
203203
return false;
204204
205205
return field.featured;
206206
},
207207
208+
// Child field executed validation
209+
onFieldValidated(res, errors, field) {
210+
// Remove old errors for this field
211+
this.errors = this.errors.filter(e => e.field != field.schema);
212+
213+
if (!res && errors && errors.length > 0) {
214+
// Add errors with this field
215+
errors.forEach((err) => {
216+
this.errors.push({
217+
field: field.schema,
218+
error: err
219+
});
220+
});
221+
}
222+
223+
let isValid = this.errors.length == 0;
224+
this.$emit("validated", isValid, this.errors);
225+
},
226+
208227
// Validating the model properties
209228
validate() {
210229
this.clearValidationErrors();
211230
212-
each(this.$children, (child) => {
231+
this.$children.forEach((child) => {
213232
if (isFunction(child.validate))
214233
{
215-
let err = child.validate();
216-
each(err, (err) => {
234+
let errors = child.validate(true);
235+
errors.forEach((err) => {
217236
this.errors.push({
218237
field: child.schema,
219238
error: err
@@ -222,7 +241,9 @@ div
222241
}
223242
});
224243
225-
return this.errors.length == 0;
244+
let isValid = this.errors.length == 0;
245+
this.$emit("validated", isValid, this.errors);
246+
return isValid;
226247
},
227248
228249
// Clear validation errors
@@ -242,8 +263,9 @@ div
242263
return field.buttons && field.buttons.length > 0;
243264
},
244265
245-
errorsVisibility(field) {
246-
return field.errors && field.errors.length > 0;
266+
fieldErrors(field) {
267+
let res = this.errors.filter(e => e.field == field);
268+
return res.map(item => item.error);
247269
}
248270
}
249271
};

0 commit comments

Comments
 (0)