Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve validations & bindings #129

Merged
merged 8 commits into from
Feb 21, 2017
Merged
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
10 changes: 7 additions & 3 deletions dev/full/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<div class="errors text-center">
<div v-for="(item, index) in validationErrors" track-by="index" class="alert alert-danger">{{ item.field.label}}: <strong>{{ item.error }}</strong></div>
</div>
<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>
<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>
</div>
<div class="col-md-6">
<pre v-if="model" v-html="prettyModel"></pre>
Expand Down Expand Up @@ -113,7 +113,11 @@
clearSelection() {
this.selected.splice(0);
this.generateModel();
},
},

onValidated(res, errors) {
console.log("VFG validated:", res, errors);
},

generateModel() {
if (this.selected.length == 1) {
Expand Down Expand Up @@ -185,7 +189,7 @@
},

validate() {
console.log("validate", this.$refs.form, this.$refs.form.validate());
//console.log("validate", this.$refs.form, this.$refs.form.validate());
return this.$refs.form.validate();
},

Expand Down
29 changes: 18 additions & 11 deletions src/fields/abstractField.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { get as objGet, each, isFunction, isString, isArray, isUndefined } from "lodash";
import { get as objGet, each, isFunction, isString, isArray } from "lodash";

export default {
props: [
Expand All @@ -7,6 +7,12 @@ export default {
"disabled"
],

data() {
return {
errors: []
};
},

computed: {
value: {
cache: false,
Expand Down Expand Up @@ -44,7 +50,7 @@ export default {
this.$emit("model-updated", newValue, this.schema.model);

if (isFunction(this.schema.onChanged)) {
this.schema.onChanged(this.model, newValue, oldValue, this.schema);
this.schema.onChanged.call(this, this.model, newValue, oldValue, this.schema);
}

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

methods: {
validate() {
validate(calledParent) {
this.clearValidationErrors();

if (this.schema.validator && this.schema.readonly !== true && this.disabled !== true) {
Expand All @@ -74,26 +80,27 @@ export default {
let err = validator(this.value, this.schema, this.model);
if (err) {
if (isArray(err))
Array.prototype.push.apply(this.schema.errors, err);
Array.prototype.push.apply(this.errors, err);
else if (isString(err))
this.schema.errors.push(err);
this.errors.push(err);
}
});

}

if (isFunction(this.schema.onValidated)) {
this.schema.onValidated(this.model, this.schema.errors, this.schema);
this.schema.onValidated.call(this, this.model, this.errors, this.schema);
}

return this.schema.errors;
let isValid = this.errors.length == 0;
if (!calledParent)
this.$emit("validated", isValid, this.errors, this);

return this.errors;
},

clearValidationErrors() {
if (isUndefined(this.schema.errors))
this.$root.$set(this.schema, "errors", []); // Be reactive
else
this.schema.errors.splice(0); // Clear
this.errors.splice(0);
},

setModelValueByPath(path, value) {
Expand Down
52 changes: 37 additions & 15 deletions src/formGenerator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ div
i.icon
.helpText(v-html='field.help')
.field-wrap
component(:is='getFieldType(field)', :disabled='fieldDisabled(field)', :model='model', :schema.sync='field', @model-updated='modelUpdated')
component(:is='getFieldType(field)', :disabled='fieldDisabled(field)', :model='model', :schema.sync='field', @model-updated='modelUpdated', @validated="onFieldValidated")
.buttons(v-if='buttonVisibility(field)')
button(v-for='btn in field.buttons', @click='btn.onclick(model, field)', :class='btn.classes') {{ btn.label }}
.hint(v-if='field.hint') {{ field.hint }}
.errors(v-if='errorsVisibility(field)')
span(v-for='(error, index) in field.errors', track-by='index') {{ error }}
.errors(v-if='fieldErrors(field).length > 0')
span(v-for='(error, index) in fieldErrors(field)', track-by='index') {{ error }}
</template>

<script>
Expand Down Expand Up @@ -126,7 +126,7 @@ div
// Get style classes of field
getFieldRowClasses(field) {
let baseClasses = {
error: field.errors && field.errors.length > 0,
error: this.fieldErrors(field).length > 0,
disabled: this.fieldDisabled(field),
readonly: this.fieldReadonly(field),
featured: this.fieldFeatured(field),
Expand All @@ -153,7 +153,7 @@ div
// Get disabled attr of field
fieldDisabled(field) {
if (isFunction(field.disabled))
return field.disabled(this.model);
return field.disabled.call(this, this.model, field, this);

if (isNil(field.disabled))
return false;
Expand All @@ -164,7 +164,7 @@ div
// Get required prop of field
fieldRequired(field) {
if (isFunction(field.required))
return field.required(this.model);
return field.required.call(this, this.model, field, this);

if (isNil(field.required))
return false;
Expand All @@ -175,7 +175,7 @@ div
// Get visible prop of field
fieldVisible(field) {
if (isFunction(field.visible))
return field.visible(this.model);
return field.visible.call(this, this.model, field, this);

if (isNil(field.visible))
return true;
Expand All @@ -186,7 +186,7 @@ div
// Get readonly prop of field
fieldReadonly(field) {
if (isFunction(field.readonly))
return field.readonly(this.model);
return field.readonly.call(this, this.model, field, this);

if (isNil(field.readonly))
return false;
Expand All @@ -197,23 +197,42 @@ div
// Get featured prop of field
fieldFeatured(field) {
if (isFunction(field.featured))
return field.featured(this.model);
return field.featured.call(this, this.model, field, this);

if (isNil(field.featured))
return false;

return field.featured;
},

// Child field executed validation
onFieldValidated(res, errors, field) {
// Remove old errors for this field
this.errors = this.errors.filter(e => e.field != field.schema);

if (!res && errors && errors.length > 0) {
// Add errors with this field
errors.forEach((err) => {
this.errors.push({
field: field.schema,
error: err
});
});
}

let isValid = this.errors.length == 0;
this.$emit("validated", isValid, this.errors);
},

// Validating the model properties
validate() {
this.clearValidationErrors();

each(this.$children, (child) => {
this.$children.forEach((child) => {
if (isFunction(child.validate))
{
let err = child.validate();
each(err, (err) => {
let errors = child.validate(true);
errors.forEach((err) => {
this.errors.push({
field: child.schema,
error: err
Expand All @@ -222,7 +241,9 @@ div
}
});

return this.errors.length == 0;
let isValid = this.errors.length == 0;
this.$emit("validated", isValid, this.errors);
return isValid;
},

// Clear validation errors
Expand All @@ -242,8 +263,9 @@ div
return field.buttons && field.buttons.length > 0;
},

errorsVisibility(field) {
return field.errors && field.errors.length > 0;
fieldErrors(field) {
let res = this.errors.filter(e => e.field == field);
return res.map(item => item.error);
}
}
};
Expand Down
Loading